`

关于Rails的用户认证

阅读更多

最近对于用户认证研究了一下,有点心得

把资源顺便整理一下,以备后用

http://notahat.com/posts/19

http://onrails.org/articles/2006/02/18/auto-login

The "remember me" checkbox

2 months ago

Here's a nifty solution that I came up with for implementing the "remember me" checkbox on login forms in Rails.

First you'll need this extension to CGI::Session::CookieStore:

# This adds the ability to dynamically set the expiry on session cookies,
# so that a session can persists across browser restarts.
#
# In your controller, just do something like:
#
#   session[:expires] = 2.weeks.from_now
#
# The expiry is also stored in the session, and double checked when the
# cookie is loaded to prevent malicious reuse of old cookies.
class CGI::Session::ExpiringCookieStore < CGI::Session::CookieStore
  def unmarshal(cookie)
    session = super(cookie)
    session = nil if session && session[:expires] && session[:expires] <= Time.now
    session
  end

  def write_cookie(options)
    options["expires"] = @data[:expires] if @data
    super(options)
  end
end

You'll need to change the session store in your environment.rb:

config.action_controller.session_store = :expiring_cookie_store

In your controller, if the "remember me" checkbox is set, just do this:

session[:expires] = 2.weeks.from_now

Voilà! Now your session (which also holds the id of the logged in user, if you implement logins in the usual way) will stick around for up to 2 weeks, even between browser restarts.

(Obviously this only works with the cookie-based session store.)

If you spot any problems or security holes with this, please let me know.

Auto-login 28

Posted by Daniel Wanja on 2006年2月18日

One of my midnight Rails projects is a “time tracking” application for which I needed auto-login. You know, the “Remember me” check box so that you don’t have to login each time you visit the application. I found a nice article written by Matt McCray describing how this was implemented for TaskThis.com at http://www.mattmccray.com/archives/category/software/rails/taskthis/. Even further he provides the full source code for the application. I didn’t take directly his auto_login.rb module but was greatly inspired by it. I also used the Login Engine Plugin that was not providing this feature, maybe this changed, so it could be simpler, but how simple implementing the auto-login can be. Note these are not the full classes just pertinent code extracts.

1. Remember me

When the user login and checks the “Remember me” checkbox, the :save_login parameter is set, the User instance remember_me method invoked and the :auth_token cookie set.

class AccountController < ApplicationController
  def login
    case @request.method
      when :post
      if @session[:user] = User.authenticate(@params[:user_login], @params[:user_password])
        flash['notice']  = "Login successful"
        if @params[:save_login] == "1"
          @session[:user].remember_me
          cookies[:auth_token] = { :value => @session[:user].remember_token , :expires => @session[:user].remember_token_expires }
        end
        redirect_back_or_default :controller => "time"
      else
        flash.now['notice']  = "Login unsuccessful"
        @login = @params[:user_login]
      end
    end
  end

  def logout
    @session[:user].forget_me if @session[:user]
    @session[:user] = nil
    cookies.delete :auth_token
  end
end

2. login_from_cookie

The next time the user visits the website the “login_from_cookie” filter is triggered. This method checks that the user is not logged in and that the :auth_token cookie is set. If that’s the case the user matching the :auth_token is searched and the token_expiration verified the the user is automatically logged in. Et voila! I guess auto_login would be more appropriate as method name.

class ApplicationController < ActionController::Base
   before_filter :login_from_cookie
   def login_from_cookie
      return unless cookies[:auth_token] && @session[:user].nil?
      user = User.find_by_remember_token(cookies[:auth_token]) 
      if user && !user.remember_token_expires.nil? && Time.now < user.remember_token_expires 
         @session[:user] = user
      end
   end
end

3. the User class

The User class has two methods to set and remove the token from the database. It’s pretty secure as from the token the user cannot be identified without having the salt, the email, and the token expiration, which is most unlikely to be recreated. It could be even more secure by just encrypting some random unique identifier. The only issue I encountered was that the user class always forces the password validation and encryption when saving. For now I just bypass validation and encryption when setting and clearing the remember_me token.

class User < ActiveRecord::Base
  def remember_me
    self.remember_token_expires = 2.weeks.from_now
    self.remember_token = Digest::SHA1.hexdigest("#{salt}--#{self.email}--#{self.remember_token_expires}")
    self.password = ""  # This bypasses password encryption, thus leaving password intact
    self.save_with_validation(false)
  end

  def forget_me
    self.remember_token_expires = nil
    self.remember_token = nil
    self.password = ""  # This bypasses password encryption, thus leaving password intact
    self.save_with_validation(false)
  end
end
关于记住用户状态的实现,大部分用户认证的插件都有。参考User+authentication+in+Ruby+on+Rails
添加一个cookie_hash字段到user中:

CODE:

class AddUserCookieHash < ActiveRecord::Migration
  def self.up
    add_column :users, :cookie_hash, :string
  end

  def self.down
    remove_column :users, :cookie_hash
  end
end
接着在登录页面,如login.html.erb中,加入:

CODE:

<%= check_box_tag :remember %> remember me然后在管理login的controller中添加:

CODE:

def login
    if request.post?
      @user = User.find_by_username(params[:login])
        if @user and @user.password_is? params[:password]
          session[:uid] = @user.id
         
          # 当用户需要被记住时,开始对cookie进行处理
          # 对cookie生成一个密钥之后放入cookie和存入数据库(user表中)
          # 其中还指定了一个cookies失效时间,默认为30天,其实可以把这个参数提出来
          if params[:remember]
            cookie_pass = [Array.new(9){rand(256).chr}.join].pack("m").chomp
            cookie_hash = Digest::MD5.hexdigest(cookie_pass + @user.password_salt)
            cookies[:userapp_login_pass] = { :value => cookie_pass, :expires => 30.days.from_now }
            cookies[:userapp_login] = { :value => @user.username, :expires => 30.days.from_now }
            User.update(@user.id, :cookie_hash => cookie_hash)
          end

          redirect_to :controller => 'panel', :action => 'secret'
        else
           @auth_error = 'Bad username or password'
        end
    end
最后在ApplicationController中加入:

CODE:

  session :session_key => '_userapp_session_id'
  before_filter :check_cookie
  
  def check_cookie
    return if session[:uid]
      if cookies[:logowanie_login]
        @user = User.find_by_username(cookies[:userapp_login])
        return unless @user
        cookie_hash = Digest::MD5.hexdigest(cookies[:userapp_login_pass] + @user.password_salt)
        if @user.cookie_hash == cookie_hash
          flash[:info] = 'You\'ve been automatically logged in' # annoying msg
          session[:uid] = @user.id
        else
          flash[:error] = 'Something is wrong with your cookie'
        end
      end
  end
而关于角色的认证可以使用插件:ActiveRBAC 
分享到:
评论

相关推荐

    基于net的超市管理系统源代码(完整前后端+sqlserver+说明文档+LW).zip

    功能说明: 环境说明: 开发软件:VS 2017 (版本2017以上即可,不能低于2017) 数据库:SqlServer2008r2(数据库版本无限制,都可以导入) 开发模式:mvc。。。

    LABVIEW程序实例-公式节点.zip

    labview程序代码参考学习使用,希望对你有所帮助。

    大米商城开源版damishop(适合外贸)

    大米外贸商城系统 简称damishop 完全开源版,只需做一种语言一键开启全球133中语言自动翻译功能,价格实现自动汇率转换,集成微信支付宝 paypal以及国外主流支付方式,自带文章博客系统。 软件架构 基于MVC+语言包模式,增加控制台,API导入产品方便对接其他系统(带json示例数据)。 使用要求 PHP7.4+ MYSQL5.6+ REDIS(可选) 安装方法 composer install 打开安装向导安装 http://您的域名/install 特色 1、缓存层增加时间与批量like删除 2、API产品导入方便对接其他系统 3、增加控制台命令行,命令行生成语言翻译包 4、后台一键开启自动翻译模式,支持全球133中语言,由于google代理翻译需要收费,这个功能需要付费。 5、可选购物车与ajax修改购物车产品 6、一键结算checkout 7、增加网站前台自定义路由 方便seo 更新日志 v3.9.7 集成鱼码支付接口,方便个人站长即使收款到账使用 v3.9.3 更新内容 1:增加ueditor与旧编辑器切换 2:增加可视化布局插

    LABVIEW程序实例-通过全局变量接收数据.zip

    labview程序代码参考学习使用,希望对你有所帮助。

    LABVIEW程序实例-日历控件.zip

    labview程序代码参考学习使用,希望对你有所帮助。

    毕设和企业适用springboot人工智能客服系统类及旅游规划平台源码+论文+视频.zip

    毕设和企业适用springboot人工智能客服系统类及旅游规划平台源码+论文+视频

Global site tag (gtag.js) - Google Analytics