简介
前后端分离之后,关于鉴权方式的选择里,除了传统的使用session之外,还可以使用jwt_token来鉴权,尤其是手机端的项目,使用jwt_token鉴权有以下好处
- 前端会比较好处理,因为session一般是装在cookies里面,如果要持久化登录的话,对于前端来说拼接cookie会额外带来一些工作,而jwt_token采用自己的独有的header
- 服务端不用维护session服务器了,这节省了非常多的开销
大致原理
流程
在前端登录成功后,会把jwt_token返回给前端,而前端之后每次访问都会在header里面加一条(Authorization: Bearer XXXX),XXXX就是放置jwt_token的位置
jwt_token结构
详细的结构可以看这里,我这里就简单的概括一下
jwt分为三段
- Header,声明该token的加密方式
- payload,主体信息全在这里,你可以在这里控制该用户的登录期限
- 验签,把第一部分和第二部分通过服务器的私钥加密,变成第三段
三段数据全部用Base64加密,然后用.
来隔开,就生成了jwt_token,一般会长这样
eyJhbGciOiJIUzI1NiJ9.eyJleHBfYXQiOiIyMDE5LTEwLTA2IDE3OjU3OjU0ICswODAwIiwiaWQiOjQsInVzZXJuYW1lIjoi57qq5Lqa55Cq77yI6LaF566h77yJIiwidXNlcl90eXBlIjoic3VwZXJfYWRtaW4iLCJtb2JpbGUiOiIxNzcyMTI3MzIzMyJ9.38VDrWZlDmAY4fiYmJo-_rDKhYzaxEwiewj9ruyVSCQ
安全性
该token的安全保障其实全靠那个私钥(其实基于https完全不用考虑安全问题),当前端试图更改payload信息来登录其他账号时,由于他不知道对称加密要用到的私钥,因此他无法生成正确的第三段信息,因此他无法通过服务器的验证
在Rails里面使用jwt_token
安装gem
gem 'jwt'
$ bundle install
写生成token和验证token的方法
可以放在user模型里,这个随意
生成jwt_token的方法
user.rb
class User < ApplicationRecord
def generate_jwt_token
hmac_secret = JWT_HMAC_SECRET ##服务器的私钥,可以是一个字符串或者钥匙,这个自己决定
payload = {
exp_at: (Time.now + 1.week).to_s,
id: id,
username: username,
user_type: user_type,
mobile: mobile
}
JWT.encode payload, hmac_secret, 'HS256'
end
...
验证方法
def self.decoded_jwt_infos token
JWT.decode(token, JWT_HMAC_SECRET, true, { algorithm: 'HS256' })[0]
end
在控制器层,写current_user方法
class Api::ApiController < ApplicationController
skip_before_action :verify_authenticity_token
def check_login
if current_user.blank?
render json: {msg: "登录失败", result: false}, status: :forbidden
end
end
def current_user
if request.headers['Authorization']&.start_with?("Bearer")
jwt_token = request.headers['Authorization'].split&.last
jwt_info = User.decoded_jwt_infos(jwt_token)
if Time.parse(jwt_info["exp_at"]) > Time.now
@current_user ||= User.unscoped.active.find_by_id(jwt_info["id"])
end
end
rescue JWT::ExpiredSignature, JWT::VerificationError
nil
end
end
剩下的就是在登录成功后将生成的token返回,可以放在body里,也可以放在headers里,这个随意