前端登录鉴权方案 JWT

239 阅读4分钟

目前我们常用的鉴权有四种:

image.png

纯cookie验证

image.png

步骤分解

  • 浏览器首次登录,服务器收到请求后去数据库校验用户名及密码

  • 校验通过后,从数据库查询对应的用户信息

  • 把非重要信息(如密码,邮箱等)通过响应体set-cookie存入到浏览器中

  • 浏览器下次请求接口,自动携带cookie信息在请求体中,其中包含了用户的信息(如username

  • 服务器拿到请求体中的cookie,如果包含username等用户信息,则校验通过

session+cookie

image.png

步骤分解

  • 浏览器首次登录,服务器收到请求后去数据库校验用户名及密码

  • 校验通过后,从数据库查询对应的用户信息

  • 在服务器进程中创建session,把用户信息保存起来

  • 设置响应体(Set-Cookie),把sessionId(一般是userId,因为userId比直接暴露username更安全)返回

  • 浏览器下次请求接口,自动携带cookie信息在请求体中,其中包含了sessionId

  • 服务器拿到请求体中的sessionId,判断sessionId对应的是哪个用户

  • 查询到对应用户后,执行后续操作。反之,权限校验失败

Token

image.png

步骤分解

  • 浏览器首次登录,服务器收到请求后去数据库校验用户名及密码

  • 校验通过后,从数据库查询对应的用户信息

  • 服务器将用户信息通过密钥生成令牌(Access Token),并返回给浏览器

  • 浏览器拿到令牌之后,可以保存到cookie或者localStoragesessionStorage

  • 浏览器下次请求接口,将Access Token放到请求头header

  • 服务端拿到请求头的token,然后通过密钥解密,校验通过后执行后续操作。反之,权限校验失败

优缺点

  • 优点:
    • 无状态可以减轻服务器压力,减少频繁查询数据库
    • 安全性高,token解密密钥只有服务端知道,客户端无法解密
  • 缺点:
    • token过期时间短,需要refresh-token配合使用,refresh token是在access token过期时重新获取token的
    • refresh token也有过期时间,会增加数据库查询次数

JWT(Json-web-tokens)

image.png

完成的JWT token长什么样?

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyaWQiOiJhIiwiaWF0IjoxNTUxOTUxOTk4fQ.2jf3kl_uKWRkwjOP6uQRJFqMlwSABcgqqcJofFH5XCo

如何生成的?

image.png

它由三部分组成:Header(头部)、Payload(负载)、Signature(签名)。

  • Header部分是一个JSON对象,描述JWT的元数据。一般描述信息为该Token的加密算法以及Token的类型。{"alg": "HS256","typ": "JWT"}的意思就是,该token使用HS256加密,token类型是JWT。这个部分基本相当于明文,它将这个JSON对象做了一个Base64转码,变成一个字符串。Base64编码解码是有算法的,解码过程是可逆的。头部信息默认携带着两个字段。

  • Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。有7个官方字段,还可以在这个部分定义私有字段。一般存放用户名、用户身份以及一些JWT的描述字段。它也只是做了一个Base64编码,因此肯定不能在其中存放秘密信息,比如说登录密码之类的。

  • Signature是对前面两个部分的签名,防止数据篡改,如果前面两段信息被人修改了发送给服务器端,此时服务器端是可利用签名来验证信息的正确性的。签名需要密钥,密钥是服务器端保存的,用户不知道。算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

步骤分解

  • 浏览器首次登录,服务器收到请求后去数据库校验用户名及密码

  • 校验通过后,从数据库查询对应的用户信息

  • 服务器将用户信息生成jwt,并返回给客户端

  • 浏览器拿到jwt之后,可以保存到cookie或者localStoragesessionStorage

  • 浏览器下次请求接口,将jwt放到请求头header中(默认格式Authorization: Bearer jwt

  • 服务端检查jwt的签名信息,从jwt中获取用户信息,并执行后续操作。反之,权限校验失败

优缺点

  • 优点:
    • 安全性高
    • 解决服务器压力,减少服务器查询次数
  • 缺点:
    • jwt需要加密

前端代码实现

// 拦截请求
request.interceptors.request.use((config)=>{
  let token = localStorage.getItem('token')
  config.headers.Authorization = token
  return config
})
// 拦截响应
request.interceptors.response.use((response)=>{
  if(response.headers.authorization){
    localStorage.setItem('token',response.headers.authorization)
  }
  return response
},function(err){
 if(err.response.status == 401){
   router.push('/login')
 }
 return Promise.reject(err)
})