2016-08-21 36 views
0

我正在将Rails 3.2应用程序迁移到更新的(更高编号的)牧场。 AuthLogic为我提供了很好的服务,显然在4年后无法运行。所以我正在转向Warden。守望者为什么不使用所有的默认策略?

下面的warden.rb文件已经从几年前编写的应用程序迁移过来......但是监狱文档建议基本界面是相同的。感觉它应该工作。

我有两种认证策略:httpauth和:params。该:params策略的作品。这里的显示认证工作日志文件中的条目:

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 [email protected] from params 
... 
[AUTH] User [email protected] authenticated with a password. 
... 
Completed 302 Found in 111.5ms (ActiveRecord: 1.0ms) 

然而,当使用httpauth(通过卷曲):

curl http://dev.projectdomain.com/clouds/bmi.svg -u user:password 

我期待看到 “检查httpauth”,然后 “检查PARAMS” ...但相反,我看到“检查参数”两次。我假设我要求看守在控制器中进行两次验证......但根据我的理解,我也应该看到“检查httpauth”。有关为什么这不起作用的任何想法?

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。我实际上有第三种策略:标记,但它不是默认策略,为简单起见,我已将它排除在外。我没有验证问题仍与代码存在修正:

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 

回答

0

看来,从同一个基类继承两种策略模样相同的策略来看守。我复制/粘贴,修正了我的httpauth策略中的一个小错误,并且它工作正常。不幸的。

我用一个模块而不是一个类来抽象常用的方法。最终解决方案:

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 
相关问题