`

关于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 
分享到:
评论

相关推荐

    关于Rails登录和验证插件http_authentication restful-authentication

    在Rails应用中,用户认证和授权是常见的需求,用于保护应用资源的安全。"http_authentication"和"restful-authentication"是两个早期的Rails登录和验证插件,它们为Rails应用提供了基本的身份验证功能。 HTTP基本...

    Rails项目源代码

    "Sign"可能是项目的登录或注册模块,它涉及用户认证和授权。在Rails中,可以使用Devise这样的gem来处理用户身份验证,提供注册、登录、密码重置等功能。用户模型通常会包含确认令牌、加密密码等相关字段。 4. **...

    Rails 101S

    - **加入用户认证功能**:增加用户注册、登录、注销等基础功能。 - **扩展用户资料**:在用户模型中增加额外字段(如用户名),并提供账号设置页面。 - **作者机制实现**:让文章与用户建立关联,实现“作者”概念。...

    web开发之rails最新调试通过购物车代码

    本压缩包中的"web开发之rails最新调试通过购物车代码"是关于使用Rails进行Web应用开发的一个实例,特别是针对购物车功能的实现。 购物车是电商网站的核心部分,它允许用户选择商品并保存这些选择以便后续购买。在...

    Rails上的API:使用Rails构建REST APIAPIs on Rails: Building REST APIs with Rails

    4. **实现认证和授权机制**:为了保证API的安全性,需要实现用户认证和权限管理功能,例如使用JWT(JSON Web Tokens)、OAuth等方式。 5. **错误处理**:定义一套统一的错误处理策略,当请求无法正确处理时能够向...

    ruby on rails社区网站开发源码

    13. **社区插件(Gems)**:Rails的生态系统中有大量高质量的第三方Gem,如Devise(用户认证)、Pundit(授权管理)、Paperclip或Carrierwave(文件上传)等,它们可以极大地扩展Rails的功能。 通过研究这个源码,...

    Ruby On Rails中文教材(PDF)

    10. **Gem包管理**:Ruby的Gem系统使得安装和管理第三方库变得简单,如Devise用于用户认证,Paperclip或Carrierwave处理文件上传,Bootstrap提供前端UI组件等。 学习Rails的过程中,实践尤为重要。通过完成实际项目...

    Ruby on Rails中文指南

    10. **会话(Sessions)**和**cookies**:Rails提供了内置的会话管理和cookie支持,用于跟踪用户状态和实现用户认证。 11. **测试(Testing)**:Rails鼓励TDD(Test-Driven Development),提供了丰富的测试工具,...

    rails-api-4.0.0

    七、安全与认证: API的安全性至关重要。常见的安全策略包括OAuth2、JWT(JSON Web Tokens)或API密钥。Rails提供如devise_token_auth这样的库来协助实现这些机制。 八、文档: 良好的API文档是开发者友好性的体现...

    ruby on rails 3 tutorial.pdf

    例如,Devise用于用户认证,CanCanCan用于授权管理,Paperclip或Carrierwave处理文件上传等。 此外,本书还会介绍Rails的安全实践,包括防止SQL注入、XSS攻击等常见Web安全问题。你将学习如何使用strong parameters...

    ruby on rails最新版

    例如,Devise用于用户认证,CanCanCan用于授权管理,Paperclip或Carrierwave处理文件上传,Stripe或PayPal集成支付功能,以及各种数据分析和报表生成库等。 总的来说,这个压缩包对于Ruby on Rails的初学者或希望...

    Ruby on Rails 4 Tutorial 中文版

    此外,还会有关于安全性的讲解,如CSRF(Cross-site request forgery)防护和如何使用Devise进行用户认证。 总之,《Ruby on Rails 4 Tutorial 中文版》是一本全面而实用的指南,涵盖了从基础到高级的Rails开发知识...

    Apress - Practical Rails Projects (Oct 2007)

    书中可能会涵盖创建用户认证系统、实现RESTful API、集成第三方服务(如支付网关或社交媒体API)以及优化性能等内容。此外,还会讲解如何部署Rails应用到服务器,如使用Capistrano进行自动化部署。 附带的源代码...

    Agile+Web+Development+with+Rails中文版.pdf

    书中会讲解如何利用这些工具进行数据库操作、表单处理、认证与授权,以及如何与其他服务和API集成。 此外,《Agile Web Development with Rails》还涵盖了测试驱动开发(TDD)和行为驱动开发(BDD)。TDD强调先写...

    ruby on rails在线考试系统

    例如,Devise用于用户认证,Cancancan进行权限控制,Paperclip或Carrierwave处理文件上传等。 8. 安全性:Rails内置了一些安全特性,如CSRF(跨站请求伪造)防护、XSS(跨站脚本攻击)防护以及参数过滤等。在考试...

    InspiniaAdmin 2.6.1 Rails_Full_Version

    1. **用户认证与授权**:内置了用户注册、登录、权限管理等功能,可以轻松实现用户身份验证和角色权限控制,确保后台的安全性。 2. **数据可视化**:集成了一系列图表库,如Chart.js和Morris.js,用于数据展示和...

Global site tag (gtag.js) - Google Analytics