Rails自带用户验证has_secure_password的使用与源码分析
来源:互联网 发布:2010nba总决赛数据 编辑:程序博客网 时间:2024/05/22 01:36
Rails自带的用户密码验证是has_secure_password方法,它使用简单,源码也容易理解。本文将介绍如何使用has_secure_password以及其源码的分析。
1. has_secure_password的使用
has_secure_password的使用非常简单,只需要如下两步:
- 为用户模型添加password_digest一列;
- 在用户模型文件中添加has_secure_password一行。
这两步完成之后就已经自动添加了用户密码验证的各种方法了,见如下代码:
# Schema: User(name:string, password_digest:string)class User < ActiveRecord::Base has_secure_passwordenduser = User.new(name: 'david', password: '', password_confirmation: 'nomatch')user.save # => false, password requireduser.password = 'mUc3m00RsqyRe'user.save # => false, confirmation doesn't matchuser.password_confirmation = 'mUc3m00RsqyRe'user.save # => trueuser.authenticate('notright') # => falseuser.authenticate('mUc3m00RsqyRe') # => userUser.find_by(name: 'david').try(:authenticate, 'notright') # => falseUser.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user
has_secure_password方法会为User model添加password和password_confirmation两个只读属性,以及一个authenticate方法,用来验证密码的正确性。
2. has_secure_password的源码分析
has_secure_password的源码非常清晰,很容易就能理解其实现机制。下面是has_secure_password的源码,我做了些简化,保留了核心部分:
def has_secure_password(options = {}) begin require 'bcrypt' rescue LoadError $stderr.puts "You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install" raise end include InstanceMethodsOnActivation include ActiveModel::Validations validate do |record| record.errors.add(:password, :blank) unless record.password_digest.present? end validates_length_of :password, maximum: ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED validates_confirmation_of :password, if: ->{ password.present? } end这段代码分为三个部分,首先是引入bcrypt依赖包,这个包提供了加密工具,然后引入了InstanceMethodsOnActivation模块,这部分是主要功能的具体实现部分,最后添加了一些验证,在这部分可以看到password_digest这个column必须要存在,否则会出现异常。下面主要来分析InstanceMethodsOnActivation这个模块。
2.1 InstanceMethodsOnActivation
这个模块的代码如下:
module InstanceMethodsOnActivation def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && self end attr_reader :password def password=(unencrypted_password) if unencrypted_password.nil? self.password_digest = nil elsif unencrypted_password.present? @password = unencrypted_password cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost) end end def password_confirmation=(unencrypted_password) @password_confirmation = unencrypted_password endend这部分代码是验证的实现细节:
- 它定义了一个authenticate方法用于验证密码(注意==优先级高于&&),相等则返回self,否则返回false;
- 声明了只读属性password并实现了其写方法,写入的同时会生成新的password_digest;
- 实现了password_confirmation的写方法。
以上就是has_secure_password的源码的实现,其实很简单,完全可以自己手写,但是rails提供方法无疑简化了开发的工作。
1 0
- Rails自带用户验证has_secure_password的使用与源码分析
- YII自带验证的源码分析
- Rails使用has_secure_password进行身份验证
- rails has_secure_password
- Rails使用Devise验证用户
- mvc 自带验证使用
- iOS系统自带指纹验证的使用
- Oracle自带的用户
- has_secure_password可以使用在update上的原因
- Android自带计算器源码 分析
- 使用 Android 自带的 proguard 混淆源码
- 使用 Android 自带的 proguard 混淆源码
- 使用 Android 自带的 proguard 混淆源码
- 使用 Android 自带的 proguard 混淆源码
- 使用 Android 自带的 proguard 混淆源码
- 使用 Android 自带的 proguard 混淆源码
- C#xml的压缩与解压还原(使用系统自带的压缩与解压)(源码分享)
- 使用rails自带方法去除html标签
- ORA-12154: TNS: 无法解析指定的连接标识符
- bzoj 1715: [Usaco2006 Dec]Wormholes 虫洞
- subString()在JDK6和JDK7中的区别
- 简单理解Struts2中拦截器与过滤器的区别及执行顺序
- 拥塞避免算法
- Rails自带用户验证has_secure_password的使用与源码分析
- Two Sum leetcode
- uva 12206 - Stammering Aliens(哈希)
- socket 编程之网络地址
- java socket 一服务器对多客户端
- 进程
- atitit.提升稳定性---hibernate 增加重试retry 机制解决数据库连接关闭
- android 时间处理(夏令时)
- 简易真正的tab栏