首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Warden没有使用所有的默认策略?

为什么Warden没有使用所有的默认策略?
EN

Stack Overflow用户
提问于 2016-08-21 23:22:13
回答 1查看 928关注 0票数 1

我正在将一个Rails 3.2应用程序迁移到更绿色(编号更高)的站点。AuthLogic一直为我提供了很好的服务,但显然在4中不起作用,所以我要过渡到典狱长。

下面的warden.rb文件是从几年前编写的一个应用程序迁移过来的。但典狱长的文档显示,基本界面是相同的。感觉应该能行得通。

我有两个身份验证策略:httpauth和:params。:params策略有效。以下是显示身份验证工作的日志文件条目:

代码语言:javascript
复制
Started POST "/user_sessions" for 127.0.0.1 at 2016-08-17 16:32:12 -0500
Processing by UserSessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "username"=>"...."}
[AUTH] checking params
[AUTH] Authenticating user jw@mustmodify.com from params
...
[AUTH] User jw@mustmodify.com authenticated with a password.
...
Completed 302 Found in 111.5ms (ActiveRecord: 1.0ms)

但是,在使用httpauth (通过curl)时:

代码语言:javascript
复制
curl http://dev.projectdomain.com/clouds/bmi.svg -u user:password

我期望看到“检查httpauth”然后是“检查参数”...但是我看到了两次“检查参数”。我想我是在要求典狱长在控制器里认证两次...但根据我的理解,我也应该看到“检查httpauth”。有没有想过为什么它不起作用?

代码语言:javascript
复制
Started GET "/clouds/bmi.svg" for 127.0.0.1 at 2016-08-17 16:22:51 -0500
Processing by CloudsController#show as SVG
  Parameters: {"id"=>"bmi"}
[AUTH] checking params
[AUTH] checking params

然后身份验证就结束了。

下面是我的config/initializers/warden.rb文件。一个音符..。由于httpauth和params使用相同的字段和方法进行身份验证,因此我将“密码检查”抽象为一个类: UserCredentialAuthentication。实际上,我还有第三个策略:token,但它不是默认策略,为了简单起见,我将其排除在外。我确实用修改后的代码验证了问题仍然存在:

代码语言:javascript
复制
Rails.application.config.middleware.use Warden::Manager do |manager|
  manager.default_strategies :httpauth, :params
end

Warden::Manager.serialize_into_session do |user|
  user.persistence_token
end

Warden::Manager.serialize_from_session do |id|
  User.where(persistence_token: id).first
end

class UserCredentialAuthentication < ::Warden::Strategies::Base
  def verify_against_old_credentials( user, password )
    Sha512.matches?( user.sha512_password, password, user.sha512_salt )
  end

  def transition_from_sha512!( user, password )
    user.password = password
    user.sha512_password = nil
    user.sha512_salt = nil
    user.save
  end

  def authenticate!
    Rails.logger.warn("[AUTH] Authenticating user #{username} from #{medium}")
    user = User.find_by_username_or_email(username)

    if user.blank?
      Rails.logger.warn("[AUTH] No Such User")
      fail "Invalid email or password"

    elsif user.sha512_password.not.blank? && verify_against_old_credentials( user, password )
      Rails.logger.warn("[AUTH] User #{user.email} authenticated with a SHA512 password.")
      transition_from_sha512!( user, password )
      success! user

    elsif user.password_digest && user.authenticate( password )
      Rails.logger.warn("[AUTH] User #{user.email} authenticated with a password.")
      success! user

    else
      Rails.logger.warn("[AUTH] Bad Password")
      fail "Invalid email or password"

    end
  end
end


Warden::Strategies.add(:httpauth, UserCredentialAuthentication) do
  def medium
    'httpAuth'
  end

  def valid?
    Rails.logger.warn("[AUTH] checking httpAuth")
    auth.provided? && auth.basic?
  end

  def auth
    @auth ||= Rack::Auth::Basic::Request.new(env)
  end

  def username
    auth.credentials[1]
  end

  def password
    auth.credentials[2]
  end
end

Warden::Strategies.add(:params, UserCredentialAuthentication) do
  def medium
    'params'
  end

  def valid?
    Rails.logger.warn("[AUTH] checking params")
    credential_params['username'] && credential_params['password']
  end

  def username
    credential_params['username']
  end

  def password
    credential_params['password']
  end

  def credential_params
    p = params.blank? ? post_params : params
    p['user_session'] || {}
  end

  def post_params
    @post_params ||= get_post_params
  end

  def get_post_params
    req = Rack::Request.new(env)

    if( req.post? )
      begin
        body = req.body.read
        req.body.rewind
        JSON.parse( body )
      end
    else
      {}
    end
  end
end
EN

回答 1

Stack Overflow用户

发布于 2016-08-21 23:56:30

对于Warden来说,从同一个基类继承的两个策略看起来像是相同的策略。我复制/粘贴,修复了httpauth策略中的一个小错误,它起作用了。不幸的是。

我使用模块而不是类来抽象公共方法。最终解决方案:

代码语言:javascript
复制
Rails.application.config.middleware.use Warden::Manager do |manager|
  manager.default_strategies [:httpauth, :params]
end

Warden::Manager.serialize_into_session do |user|
  user.persistence_token
end

Warden::Manager.serialize_from_session do |id|
  User.where(persistence_token: id).first
end

module UserCredentialAuthentication
  def verify_against_old_credentials( user, password )
    Sha512.matches?( user.sha512_password, password, user.sha512_salt )
  end

  def transition_from_sha512!( user, password )
    user.password = password
    user.sha512_password = nil
    user.sha512_salt = nil
    user.save
  end

  def authenticate!
    Rails.logger.warn("[AUTH] Authenticating user #{username} from #{medium}")
    user = User.find_by_username_or_email(username)

    if user.blank?
      Rails.logger.warn("[AUTH] No Such User")
      fail "Invalid email or password"

    elsif user.sha512_password.not.blank? && verify_against_old_credentials( user, password )
      Rails.logger.warn("[AUTH] User #{user.email} authenticated with a SHA512 password.")
      transition_from_sha512!( user, password )
      success! user

    elsif user.password_digest && user.authenticate( password )
      Rails.logger.warn("[AUTH] User #{user.email} authenticated with a password.")
      success! user

    else
      Rails.logger.warn("[AUTH] Bad Password")
      fail "Invalid email or password"

    end
  end
end


Warden::Strategies.add(:httpauth) do
  include UserCredentialAuthentication

  def medium
    'httpAuth'
  end

  def valid?
    Rails.logger.warn("[AUTH] checking httpAuth")
    auth.provided? && auth.basic?
  end

  def username
    auth.credentials[0]
  end

  def password
    auth.credentials[1]
  end

  def auth
    @auth ||= Rack::Auth::Basic::Request.new(env)
  end
end

Warden::Strategies.add(:params) do
  include UserCredentialAuthentication

  def medium
    'params'
  end

  def valid?
    Rails.logger.warn("[AUTH] checking params")
    credential_params['username'] && credential_params['password']
  end

  def username
    credential_params['username']
  end

  def password
    credential_params['password']
  end

  def credential_params
    p = params.blank? ? post_params : params
    p['user_session'] || {}
  end

  def post_params
    @post_params ||= get_post_params
  end

  def get_post_params
    if( request.post? )
      begin
        body = request.body.read
        request.body.rewind
        JSON.parse( body )
      end
    else
      {}
    end
  end
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39065812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档