`

使用和学习authenticate插件-AuthenticatedSystem类

阅读更多
这篇文章简单的分析一下AuthorenticatedSystem类,我把相关连的代码放在一起,方便分析,首先列出最常用的三个方法
ruby 代码
 
  1. # Returns true or false if the user is logged in.  
  2. # Preloads @current_user with the user model if they're logged in.  
  3. def logged_in?  
  4.   current_user != :false  
  5. end  
  6.   
  7. # Accesses the current user from the session.  
  8. def current_user  
  9.   @current_user ||= (session[:user] && User.find_by_id(session[:user])) || :false  
  10. end  
  11.   
  12. # Store the given user in the session.  
  13. def current_user=(new_user)  
  14.   session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id  
  15.   @current_user = new_user  
  16. end  
调用logged_in?的时候,会调用current_user方法,如果是第一次调用,会进而调用模型类的find方法,使用id来进行查找,否则直接返回@current_user实例变量
调用current_user=()方法,如果传入参数是nil或者symbol,session[:user]被设置为nil,否则设置为相应模型类的id,同时设置@current_user实例变量
使用@current_user大概是为了减少数据库查询次数
ruby 代码
 
  1. def login_required  
  2.   username, passwd = get_auth_data  
  3.   self.current_user ||= User.authenticate(username, passwd) || :false if username && passwd  
  4.   logged_in? && authorized? ? true : access_denied  
  5. end  
  6.   
  7. def authorized?  
  8.   true  
  9. end  
  10.   
  11. @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)  
  12. # gets BASIC auth info  
  13. def get_auth_data  
  14.   auth_key  = @@http_auth_headers.detect { |h| request.env.has_key?(h) }  
  15.   auth_data = request.env[auth_key].to_s.split unless auth_key.blank?  
  16.   return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nilnil]   
  17. end  
  18.   
  19. def access_denied  
  20.   respond_to do |accepts|  
  21.     accepts.html do  
  22.       store_location  
  23.       redirect_to :controller => '/account', :action => 'login'  
  24.     end  
  25.     accepts.xml do  
  26.       headers["Status"]           = "Unauthorized"  
  27.       headers["WWW-Authenticate"] = %(Basic realm="Web Password")  
  28.       render :text => "Could't authenticate you":status => '401 Unauthorized'  
  29.     end  
  30.   end  
  31.   false  
  32. end    
  33.   
  34. def store_location  
  35.   session[:return_to] = request.request_uri  
  36. end  
login_required是一个filter方法,通过在ApplicationController类中include AuthorenticatedSystem类,然后在相应的模型类中定义一个before_filter :login_required来使用,login_required通过get_auth_data方法从request请求中获得auth_key和auth_data,将auth_data反编码后取出其中的值,此返回值是一个数组,如果request请求中不包含auth_data,则返回[nil,nil]
如果get_auth_data返回一个[nil,nil],或者request包含的用户名密码不正确,会导致session[:user]和@current设置为:false,logged_in?返回false,导致最终调用access_denied方法,此方法会记录用户当前请求的连接地址,放入一个叫session[:return_to]的session中,并且重定向到login方法,session[:return_to]会在login中用到。
ruby 代码
 
  1. def self.included(base)  
  2.   base.send :helper_method:current_user:logged_in?  
  3. end  
logged_in?方法被注册为helper方法,从而可以在视图中使用,用来控制视图逻辑。
ruby 代码
 
  1. # When called with before_filter :login_from_cookie will check for an :auth_token  
  2. # cookie and log the user back in if apropriate  
  3. def login_from_cookie  
  4.   return unless cookies[:auth_token] && !logged_in?  
  5.   user = User.find_by_remember_token(cookies[:auth_token])  
  6.   if user && user.remember_token?  
  7.     user.remember_me  
  8.     self.current_user = user  
  9.     cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }  
  10.     flash[:notice] = "Logged in successfully"  
  11.   end  
  12. end  
login_from_cookie方法应该置于ApplicationController中并且申明为before_filter,这样可以在整个网站获得remember_me功能
ruby 代码
 
  1. def login_from_cookie  
  2.   return unless cookies[:auth_token] && !logged_in?  
  3.   user = User.find_by_remember_token(cookies[:auth_token])  
  4.   if user && user.remember_token?  
  5.     user.remember_me  
  6.     self.current_user = user  
  7.     cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }  
  8.     flash[:notice] = "Logged in successfully"  
  9.   end  
  10. end  
如果cookies中不包含:auth_token,或者用户已经登录,则直接返回。根据cookies[:auth_token]查找user,调用remember_token?方法判断用户是否已经过期(插件默认过期时间为两个星期)
ruby 代码
  1. def remember_token?  
  2.   remember_token_expires_at && Time.now.utc < remember_token_expires_at   
  3. end 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics