Rails 用户登录cookie


所有认证都包括两块:
1)生成 auth_token 并下行发给客户端;
2)客户端和请求数据一并上行到服务器,服务器解析出用户 ID ;
注意:
1)auth_token 不能伪造;
2)auth_token 上行最好不要侵入上行的业务逻辑参数,也就是用 cookies 或者  headers 上行 auth_token;
3)修改密码,auth_token 过期(可选功能);
4)不同的 client 使用不同的 auth_token(可选功能);


current_user

It is defined by several gems, e.g. Devise
You'll need to store the user_id somewhere, usually in the session after logging in. It also assumes your app has and needs users, authentication, etc.

Typically, it's something like:

class ApplicationController < ActionController::Base
  def current_user
    return unless session[:user_id]
    @current_user ||= User.find(session[:user_id])
  end
end


This assumes that the User class exists, e.g. #{Rails.root}/app/models/user.rb.


Updated: avoid additional database queries when there is no current user.


is sessions sort of like a commonly used controller/model for the purpose of controlling a users login status? or is it built into rails?


session is built into Rails. By default, it uses a cookie to maintain a client's state between requests. See guides.rubyonrails.org/security.html#sessions for more info.


NOTE: If you're reading this answer, be sure to include return unless session[:user_id] as shown in Zach's answer -- without that, every if current_user check while signed out will trigger another database query.

登录后的认证(Authentication)

我们可以考虑用下面的两个 gems 之一
https://github.com/wardencommunity/warden
https://github.com/jwt/ruby-jwt/


添加 checkbox 的代码 到 login.html.erb 中的提交按钮上方,添加

<dl class="form remember-me">
  <%= check_box_tag :remember_me, 1, params[:remember_me] %>
  <%= label_tag :remember_me %>
</dl>


user.css.scss 中要追加这些内容


.remember-me {

 * {
   width: auto;
 }
 #remember_me {
   margin-left: 0;
 }


}


为每个用户生成一个唯一的 auth_token


如果直接把用户的 id 存放到 cookie 中,这个就太容易被人伪造了,所以来为每一个用户生成一串随机数,用来代表他的身份吧。


命令行执行:


rails g migration AddAuthTokenToUsers auth_token:string


rake db:migrate



user.rb 中,添加下面的代码,道理很简单,就是给每个用户生成一串不重复的随机数

before_create { generate_token(:auth_token) }

def generate_token(column)
  begin
    self[column] = SecureRandom.urlsafe_base64
  end while User.exists?(column => self[column])
end


如果数据库中又以前已经注册过的老用户,那没有 auth_token 后面就会出问题,可以写个 rake task 来给他们都 添加 token,但是这里我的数据库里也就只有一个用户了,直接到 console 中 destroy 了就行了。


相应的代码调整 users_controller.rb 中的 create_login_session 方法中要做这样的调整

+ if params[:remember_me]
+   cookies.permanent[:auth_token] = user.auth_token
+ else
+   cookies[:auth_token] = user.auth_token
+ end


退出登录的代码也要改,也就是 users_controller.rb 的 logout 方法中

cookies.delete(:auth_token)


application_controller.rb 中 current_user 也要改写了

def current_user
  @current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end



来登录一下试试,如果勾选 “ remember me ”,这样到 chrome devtools -> Resources 标签下,可以看到 cookie 非让 过期时间设置为 session ,反正如果勾选了,过期时间就是 20 年后了,这些都是 API 文档 上写得明明白白的。


补充一个常用的小技巧,用户注册成功之后,让用户重新 login 一遍,显得有些麻烦,所以可以到 users_controller.rb 的 create 方法中,user.save 语句之后添加


ruby cookies[:auth_token] = user.auth_token


这样,用户注册结束后,也就直接登录进来了。
阅读量: 362
发布于:
修改于: