什么是Restful Authenticaiton:
Restful Authentication是Rails的认证系统插件,它为你生成一个REST风格的认证模板。
具体的概念和生成操作请见:Rails宝典之六十七式:restful_authentication
, Rails插件:Restful Authenticaiton.
本篇为你讲述Restful Authentication的具体实现。
认证系统:
想象一下,现在大部分网站所提供的认证系统是什么样子的?
流程:注册 -》 激活 -》登录 -》登出
注册需要什么? 用户名,密码,email。
记住我:登录时可以选择记住用户名密码一段时间,在这段时间内不再用输入用户名和密码。
这是现在大部分网站的注册和登录系统需要的模板。而只要一个命令,Restful Authentication就为你生成了User model, 管理注册和登录的controller,相应的页面,mailer等等。让我们来看看代码吧。
实现:
User model:
# attributes相关的代码
attr_accessor :password # 不需要保存明文密码到数据库
validates_presence_of :login, :email
validates_presence_of :password, :if => :password_required?
validates_presence_of :password_confirmation, :if => :password_required?
validates_length_of :password, :within => 4..40, :if => :password_required?
validates_confirmation_of :password, :if => :password_required?
validates_length_of :login, :within => 3..40
validates_length_of :email, :within => 3..100
validates_uniqueness_of :login, :email, :case_sensitive => false
before_save :encrypt_password # 为密码加密
# anything else you want your user to change should be added here.
# mass assignment
attr_accessible :login, :email, :password, :password_confirmation
# Encrypts some data with the salt.
def self.encrypt(password, salt)
Digest::SHA1.hexdigest("--#{salt}--#{password}--")
end
protected
def encrypt_password # 加密密码
return if password.blank?
self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
self.crypted_password = encrypt(password)
end
def password_required? # 当注册时和修改密码时
crypted_password.blank? || !password.blank?
end
显而易见,这里为大家生成了一个基本的User model,它包含注册所需的一些基本信息,比如用户名,密码,email。并加上了一些简单的validates,以及为密码加密等。
# 与激活有关的代码
before_create :make_activation_code # 创建时生成一个激活码
# Activates the user in the database.
def activate # 激活,把activation_code置为nil
@activated = true
self.activated_at = Time.now.utc
self.activation_code = nil
save(false)
end
def active?
# the existence of an activation code means they have not activated yet
activation_code.nil?
end
# Returns true if the user has just been activated.
def recently_activated?
@activated
end
protected
def make_activation_code
self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
end
# 与认证有关的代码
# Authenticates a user by their login name and unencrypted password. Returns the user or nil.
# 查找数据库是否有相关login的用户存在,并匹配密码。
def self.authenticate(login, password)
u = find :first, :conditions => ['login = ? and activated_at IS NOT NULL', login] # need to get the salt
u && u.authenticated?(password) ? u : nil
end
def authenticated?(password)
crypted_password == encrypt(password)
end
# 与“记住我”相关的代码
def remember_token?
remember_token_expires_at && Time.now.utc < remember_token_expires_at
end
# These create and unset the fields required for remembering users between browser closes
def remember_me
remember_me_for 2.weeks
end
def remember_me_for(time)
remember_me_until time.from_now.utc
end
def remember_me_until(time)
self.remember_token_expires_at = time
self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
save(false)
end
def forget_me
self.remember_token_expires_at = nil
self.remember_token = nil
save(false)
end
SessionsController:
# 当remember me时,设置cookie。
cookies[:auth_token] = { :value => self.current_user.remember_token ,
:expires => self.current_user.remember_token_expires_at }
就主要介绍一下model内的代码吧。controller, mailer, observer的代码都比较简单,不再赘述。不过有块代码比较重要,那就是lib下面的AuthenticatedSytem module。
这个module里面比较重要的方法有:
# 设置session
# Store the given user id in the session.
def current_user=(new_user)
session[:user_id] = new_user ? new_user.id : nil
# 如果认证失败,则赋@current_user为false,避免在获取current_user时再访问数据库
@current_user = new_user || false
end
# Accesses the current user from the session.
# Future calls avoid the database because nil is not equal to false.
# 此方法将被login_required调用,它会去尝试用三种不同的方式认证。其中第三种直接用客户端存储的
# auth_token cookied进行认证(即remember me的方式)。
def current_user
@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
end
def login_required
authorized? || access_denied
end
def logged_in?
!!current_user
end
def authorized?
logged_in?
end
# Called from #current_user. First attempt to login by the user id stored in the session.
def login_from_session
self.current_user = User.find_by_id(session[:user_id]) if session[:user_id]
end
# Called from #current_user. Now, attempt to login by basic authentication information.
def login_from_basic_auth
authenticate_with_http_basic do |username, password|
self.current_user = User.authenticate(username, password)
end
end
# Called from #current_user. Finaly, attempt to login by an expiring token in the cookie.
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at }
self.current_user = user
end
end
代码就讲到这里吧。其实代码挺好懂,可以直接看生成的代码。
配置
在生成完代码之后,来看看如何进行一些简单的配置。
首先是router和observer的配置,很多教程都有。不再赘述。主要讲一下如何给controller设置filter吧。
一般在application.rb里面加上这两句,这样所有的controller都需要登录才能访问。
include AuthenticatedSystem
before_filter :login_required
当然,你可以为一些controller skip_before_filter。比如UsersController和SessionsController中的一些action就应该skip。
关于这个include AuthenticatedSystem,有个很奇妙的地方。
我们发现里面的current_user方法不仅在controller里面可以被使用,而且在view里面也可以直接被使用。
原来是因为:
# Inclusion hook to make #current_user and #logged_in?
# available as ActionView helper methods.
def self.included(base)
base.send :helper_method, :current_user, :logged_in?
end
Rails Session
看到这里,可能大家有个疑惑。在Rails里面是怎么直接拿到session的。通过观察,我发现Rails对session已经做了管理。你可以直接看cookie,会发现有一个session_id,它利用这个session_id直接找到你的session。所以,你的使用就如此简单:
session[:user_id]
完毕
分享到:
相关推荐
4. **路由(Routing)**: RESTful-Authentication利用Rails的RESTful路由,将URL映射到特定的控制器动作,如/users/login对应于sessions控制器的create动作。 5. **测试(Test)**: 在lib和test目录下,包含着插件的源...
根据提供的文件信息,我们可以推断出这是一本关于如何使用Ruby on Rails框架来构建RESTful应用程序和服务的专业书籍。书名为《RESTful Rails Development》,作者为Silvia Puglisi,出版时间为2015年10月。接下来,...
**Rails 3 in Action** 这本书介绍了 **Ruby on Rails**(简称 Rails)这一 Web 开发框架的核心概念和技术细节。Rails 自发布以来便以其优雅、高效、易于使用的特性而闻名,它极大地简化了 Web 应用程序的开发过程。...
在Rails 6中开发纯后端API项目是一个常见的任务,特别是在构建现代Web应用程序时,前端与后端分离的架构越来越流行。Rails作为一个强大的Ruby框架,提供了丰富的功能来帮助开发者高效地构建API服务。下面我们将详细...
8. **RESTful Design**:REST(Representational State Transfer)是一种架构风格,书中强调了如何遵循REST原则设计优雅的Rails应用。 9. **Rails与ASP.NET、C#、J2EE、Java的比较**:虽然本书主要关注Rails,但也...
它在后端使用Ruby on Rails生成RESTful API,在前端使用React / Redux,并使用Pusher无缝实现WebSockets。 特征 使用Devise通过自动演示登录进行用户身份验证 即时通讯 讯息格式 通知事项当前频道通知 频道数 直接...
为此,我们尝试将我们在其他 Web 框架中看到的最好的东西结合起来,包括用其他语言实现的框架,例如 Ruby on Rails、ASP.NET MVC 和 Sinatra。 Laravel易于访问,但功能强大,为大型,强大的应用程序提供了所需的...
rails2.0的内容管理系统,可以发布文档、CVS库和Web资源3中资源,其中文档可以上传下载附件。支持打Tag。用户注册登录使用restful_authentication,分页使用will_paginate,Gem版本1.3.5
MeetingZero Rails API 是一个基于 Ruby 开发的API接口,它为开发者提供了与MeetingZero平台交互的能力。Ruby是一种面向对象的编程语言,以其简洁、优雅的语法而受到许多Web开发者的喜爱,尤其是对于构建Web服务和...
6. **Rails API**:在与Angular结合使用时,Rails通常作为API服务器,提供RESTful接口。`config/routes.rb`文件定义了路由规则,`controllers`目录下的文件处理HTTP请求,`models`处理数据模型,而`serializers`用来...
5. **RESTful API**:如果前后端分离,后端可能提供RESTful API接口,供前端调用进行数据交换。API设计应遵循统一接口原则,如HTTP动词(GET、POST、PUT、DELETE)对应资源的操作。 6. **安全性**:投票系统的安全...
RailsAPI 是一个专门为构建RESTful API设计的Ruby on Rails框架的子集。它专注于提供一个轻量级的、高效的环境,用于开发仅处理JSON或XML数据的后端服务,而无需传统的Web应用程序视图和路由。RailsAPI的目标是减少...
GYMIFY API 使用Ruby on Rails构建的RESTFUL API。 该应用程序公开了健身房前端应用程序的API端点。 该应用程序允许用户注册,登录,查看培训师并与培训师预约约会。终点此api公开了两个端点,可以使用...
2. **资源(Resources):**Rails中的资源路由可以简化RESTful API的创建,通过`resources :controller_name`定义,可以自动生成CRUD操作对应的路由。 3. **控制器(Controllers):**处理请求并返回响应的地方,API的...
这可能是一个使用Java、Python、Node.js、Ruby on Rails等后端技术构建的Web服务。 2. **数据库管理**:主播电台的数据,如主播信息、直播记录、用户互动数据等,都需要存储在数据库中。常见的数据库选择有MySQL、...