zoukankan      html  css  js  c++  java
  • Ruby Rails学习中:添加安全密码

    接上篇

    一. 添加安全密码

    我们已经为 name 和 email 字段添加了验证规则, 现在要加入用户所需的最后一个常规属性: 安全密码。每个用户都要设置一个密码(还要二次确认), 数据库中则存储经过哈希(hash)加密后的密码(这里的hash是加密算法)。

    验证身份的方法是, 获取用户提交的密码, 哈希加密, 再与数据库中存储的密码哈希值对比。如果二者一致, 用户提交的就是正确的密码, 用户的身份也就通过验证了。我们要对比的是密码哈希值, 而不是原始密码, 所以不用在数据库中存储用户的密码。因此, 就算被“脱库”了, 用户的密码仍然安全。

    1.计算密码哈希值

    我们使用的安全密码机制基本上用一个 Rails 方法即可实现,这个方法是 has_secure_password 。我们要在User 模型中调用这个方法, 如下所示:

    在模型中调用这个方法后, 会自动添加如下功能:

    • 在数据库中的 password_digest 列存储安全的密码哈希值;
    • 获得一对虚拟属性, 18 password 和 password_confirmation ,而且创建户对象时会执行存在性验证和匹配验证;
    • 获得 authenticate 方法,如果密码正确,返回对应的用户对象,否则返回 false 。

    has_secure_password 发挥功效的唯一要求是, 对应的模型中有个名为 password_digest 的属性。(digest(摘要)是哈希加密算法中的术语。“密码哈希值”和“密码摘要”是一个意思。) 对 User 模型来说,我们要实现下图所示的数据模型。

    为了实现上图中的数据模型, 首先要创建一个适当的迁移文件, 添加 password_digest 列。迁移的名字随意, 不过最好以 to_users 结尾, 因为这样 Rails 会自动生成一个向 users 表添加列的迁移。我们把这个迁移命名为 add_password_digest_to_users , 生成迁移的命令如下:

    $ rails generate migration add_password_digest_to_users password_digest:string

    注:在这个命令中,我们还加入了参数 password_digest:string , 指定想添加的列名和类型。加入 password_digest:string 后, 我们为 Rails 提供了足够的信息, 它会为我们生成一个完整的迁移, 如下图所示:

    (1).向 users 表添加 password_digest 列的迁移

    打开文件:db/migrate/[timestamp]_add_password_digest_to_users.rb

    这个迁移使用 add_column 方法把 password_digest 列添加到 users 表中。执行下述命令在数据库中运行迁移:

    $ rails db:migrate

    has_secure_password 方法使用先进的 bcrypt 哈希算法计算密码摘要。使用 bcrypt 计算密码哈希值, 就算攻击者设法获得了数据库副本也无法登录网站。为了在演示应用中使用 bcrypt, 我们要把 bcrypt gem 添加到 Gem-file 文件中, 如下图所示:

    (2).把 bcrypt gem 添加到 Gemfile 文件中

    执行 bundle install 命令:

    $ bundle install

    2.用户有安全的密码

    现在我们已经在 User 模型中添加了 password_digest 属性, 也安装了 bcrypt, 下面可以在 User 模型中添加 has_secure_password 方法了, 如下图所示:

    (1).在 User 模型中添加 has_secure_password 方法 RED

    打开文件:app/models/user.rb

    我们在前面说过, has_secure_password 会在 password 和 password_confirmation 两个虚拟属性上执行验证, 但是现在前面创建 @user 变量时没有设定这两个属性:

    所以,为了让测试组件通过, 我们要添加这两个属性, 如下图所示:

    (2).添加密码和密码确认 GREEN

    打开文件:test/models/user_test.rb

    现在测试应该可以通过了:

    3.密码的最短长度

    一般来说, 最好为密码做些限制, 让别人更难猜测。在 Rails 中增强密码强度有很多方法, 简单起见, 我们只限制最短长度, 而且要求密码不能为空。最短长度为 6 是个不错的选择, 针对这个验证的测试如下图所示:

    (1).测试密码的最短长度 RED

    打开文件:test/models/user_test.rb

    注意这段代码中使用的双重赋值:
    @user.password = @user.password_confirmation = "a" * 5
    这行代码同时为 password 和 password_confirmation 赋值,值是长度为 5 的字符串,使用字符串连乘创建。
    参照 name 属性的 maximum 验证,你或许能猜到限制最短长度所需的代码:
    validates :password, length: { minimum: 6 }
    在上述代码的基础上,还要加上存在性验证,得出的 User 模型如下图所示。( has_secure_pass-word 方法本身会验证存在性,但是可惜,只会验证有没有密码,因此用户可以创建 “”(6 个空格)这样的无效密码。)

    (2).实现安全密码的全部代码 GREEN

    打开文件:app/models/user.rb

    现在,测试应该可以通过了:

    4.创建并验证用户的身份

    至此, 基本的 User 模型已经完成了。接下来, 我们要在数据库中创建一个用户, 为以后开发的用户资料页面做准备。同时也看一下在 User 模型中添加 has_secure_password 方法后的效果, 还要用一下重要的 authen-ticate 方法

    因为现在还不能在网页中注册, 我们要在 Rails 控制台中手动创建新用户。为了方便, 我们会使用前面所说的 create 方法。注意, 不要在沙盒模式中启用控制台, 否则结果不会存入数据库。我们要使用 rails console 启动普通的控制台, 然后使用有效的名字和电子邮件地址, 以及密码和密码确认, 创建一个用户:

    注:这里, 我出了一个莫名奇妙的BUG(上图是我改完BUG之后才能通过的结果), 先暂停补充一下:

    (1).修改BUG

    BUG内容为:

    You don't have bcrypt installed in your application. 
    Please add it to your Gemfile and run bundle install

    我Gemfile文件已经添加并按装过bcrypt, 并且装了好几个版本都出现了这个问题

    解决步骤:先删掉现有的所有的bcrypt包

    gem uninstall bcrypt

    查看gem列表是否还存在bcrypt

    gem list bcrypt

    然后:关掉IDE和正在运行的Ruby Rails项目

    再关掉正在使用的终端

    然后重新打开终端,定位到自己的项目,添加好Gemfile文件中的包

    bundle install

    然后就好了,莫名奇妙。。。

    (2).我们继续

    好了改完BUG, 为了确认结果, 我们使用 SQLite 数据库浏览器查看开发数据库( db/development.sqlite3 )中的 users 表, 如下图所示:

    回到控制台,查看 password_digest 属性的值, 由此可以看出 has_secure_password 方法的作用:

    注:这是创建用户对象时指定的密码( "foobar" )的哈希值。这个值由 bcrypt 计算得出, 很难反推出原始密码。

    前面说过, has_secure_password 方法会自动在对应的模型对象中添加 authenticate 方法。这个方法会计算给定密码的哈希值, 然后与数据库中 password_digest 列的值比较, 以此判断用户提供的密码是否正确。

    我们可以在刚创建的用户上试几个错误密码:

    我们提供的密码都是错误的, 所以 user.authenticate 返回 false 。如果提供正确的密码, authenticate 方法会返回数据库中对应的用户

    会使用 authenticate 方法把注册的用户登入网站。其实, authenticate 方法返回的用户对象并不重要, 关键是这个值是“真值”。前面说过,  !! 会把对象转换成相应的布尔值。

    我们可以使用这种方式确认:

    。。。

    下班了,先到这把,做个总结:

    二. 总结

    • 使用迁移可以修改应用的数据模型;
    • Active Record 提供了很多创建和处理数据模型的方法;
    • 使用 Active Record 验证可以在模型的数据上添加约束条件;
    • 常见的验证有存在性、长度和格式;
    • 正则表达式晦涩难懂,但功能强大;
    • 数据库索引可以提升查询效率,而且能在数据库层实现唯一性约束;
    • 可以使用内置的 has_secure_password 方法在模型中添加一个安全的密码。
  • 相关阅读:
    minio 对于压缩的处理
    mino federation 功能
    Full Schema Stitching with Apollo Server
    GraphQL Gateway Architectures
    Modularizing your graphQL schemas
    gearman openresty 集成试用
    madlib 集成 hasura graphql-engine 试用
    Oracle数据库--解决单张表中数据量巨大(大数据、数据量上百万级别,后查询,更新数据等耗时剧增)
    绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来
    几款开源的ETL工具及ELT初探
  • 原文地址:https://www.cnblogs.com/rixian/p/11728163.html
Copyright © 2011-2022 走看看