devise是rails用的比较多的一个用户登陆注册模块,研究了下他的登陆以及验证的策略(虽说还没有完全吃透),先记录下。 devise的具体使用可以参照他的文档 devise的认证机制是基于warden ,所以要先了解一下warden才能理解。用户名以及密码的验证我们这里暂且不提,主要看一下sign_in方法做了什么,以及登陆之后下次请求是如何把已登录的信息带过来验证的。 1.先看下sign_in方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def sign_in (resource_or_scope, *args)
options = args.extract_options!
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource = args.last || resource_or_scope
expire_data_after_sign_in!
if options[:bypass ]
warden.session_serializer.store(resource, scope)
elsif warden.user(scope) == resource && !options.delete(:force )
true
else
warden.set_user(resource, options.merge!(scope: scope))
end
end
warden.session.store方法,会把user id存入env[‘rack.session’][‘warden.user.user.key’]中1
2
3
4
5
6
7
8
9
10
11
12
13
def store (user, scope)
return unless user
method_name = "#{scope} _serialize"
specialized = respond_to?(method_name)
session[key_for(scope)] = specialized ? send(method_name, user) : serialize(user)
end
def serialize_into_session (scope = nil , &block)
method_name = scope.nil ? ? :serialize : "#{scope} _serialize"
Warden::SessionSerializer.send :define_method , method_name, &block
end
2.已登陆成功之后,通过authenticate_user! 来验证是否登陆1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def self .define_helpers (mapping)
mapping = mapping.name
class_eval <<-METHODS, __FILE__ , __LINE__ + 1
def authenticate_
opts[:scope ] = :
warden.authenticate!(opts) if !devise_controller? || opts.delete(:force )
end
def
!!current_
end
def current_
@current_
end
def
current_
end
METHODS
ActiveSupport.on_load(:action_controller ) do
helper_method "current_#{mapping} " , "#{mapping} _signed_in?" , "#{mapping} _session"
end
end
[查看此文件可知](https: //github.com/hassox /warden/blob /master/lib /warden/proxy .rb)最后是通过获取env["rack.session" ]['warden.user.user.key' ]来获取到当前登陆的用户的
Tips: 查看一个方法调用的位置:
method(:sign_in )
warden.session_serializer.method(:store ).source_location
参考文档 warden wiki warden源码解析 rack中间件warden的机制 rack安全