我将Rails 3.2应用程序迁移到更绿色(编号更高)的牧场。 AuthLogic很好地为我提供了很好的帮助,显然在4中没有工作。所以我已经过渡到Warden。
下面的warden.rb文件已经从几年前编写的应用程序中迁移出来了......但是,warden文档表明基本界面是相同的。感觉它应该有用。
我有两种身份验证策略: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 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)时:
curl http://dev.projectdomain.com/clouds/bmi.svg -u user:password
我希望看到"检查httpauth"那么"检查参数" ......但我看到"检查参数"两次。我假设我要求看守在控制器中进行两次验证......但根据我的理解,我也应该看到"检查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使用相同的字段和方法进行身份验证,所以我抽象了#34;密码检查"东西到单个类: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 :(得分:0)
似乎从同一个基类继承的两个策略看起来与Warden的策略相同。我复制/粘贴,修复了我的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