登录方案总结

156 阅读5分钟

此篇为自己学习过程中的总结,特此记录

一、认证系统演变

1.1 session、cokie实现登录机制

为什么我们需要Cookie和Session?这就需要从HTTP协议说起。 HTTP协议是无状态的,也就是说每次请求都是独立的不受之前请求的影响。它的执行情况和结果与前面的请求和之后的请求都没有直接关系。简单来说就是,对服务器来说每次的请求都是全新的。

状态可以理解为客户端和服务端某次会话产生的数据,那么HTTP的无状态就不会对这些数据进行保存。但是会话中产生的数据又是沃恩需要的,也就是说要保持状态。因此在这样的场景下Cookie就诞生了。

cookie虽然在一定程度上解决了保持状态的需求,但是因为cookie最大指支持4096字节,以及cookie保存在客户端可能被拦截窃取,因此需要一种新的东西,它能支持更多字节且能保存在服务器,有较高的安全性,于是session应运而生。

1.1.1 工作原理

客户端携带登录凭证(用户名、密码)请求服务端,服务端验证通过后生成认证相关的session并保存。然后将对应session_id返回给客户端,客户端把session_id保存在cookie中。此后客户端请求都会携带session_id。服务端可以根据接收到session_id的就能查询到维护的session信息。

image.png

优点:

  • 可以后台主动操作session(删除修改等操作)
  • session保存在服务端,相对较安全
  • 结合cookie使用,较为灵活兼容性较好

缺点:

  • cookie + session跨域不友好
  • 占用大量服务器内存,增加服务器开销
  • 分布式环境需要做session共享机制,可将session存储到数据库或redis
  • 基于cookie机制容易被CSRF

1.2 Token登录

使用token实现登录的原理也很简单,客户端携带登录凭证(用户名、密码)请求服务端,服务端验证后生成token存储并返回给客户端以后客户端请求头都携带token访问,服务端校验token有效性,有效表示用户已登录

image.png

生成的token我们可以存储在redis或者数据库,客户端拿到返回的token后放到请求头,后续请求服务端需要验证客户端请求头是否携带token信息然后拿获取到的token去数据库或redis查询验证token有效性

优点:

  • 可操作session: 后台可以控制session失效
  • 支持跨域访问:传统cookie是无法跨域的,而将token放在请求头中解决了无法跨域的问题
  • 更适用于移动端:当客户端是非浏览器平台时,cookie是无法支持的,使用token就不存在这一问题
  • CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF
  • 易扩展:在分布式环境中,可以使用redis存储session实现session共享更利于服务扩展,不再受限于传统sess ion限制

缺点:

  • session维护在数据库或redis中,需要占用额外资源,每次登录都需要查询验证token有效性

1.3 JWT登录

JSON Web 令牌 (jwt.io/introductio… 是一种开放标准 (RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间以 JSON 对象的形式安全地传输信息。此信息可以验证和信任,因为它是经过数字签名的。JWT 可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名

1.3.1 JWT结构

Header

通常由两部分组成:令牌类型和使用的签名算法

例如:

{ "alg": "HS256", "typ": "JWT" }

然后被Base64Url编码形成JWT第一部分

payload

令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的语句

例如:

{ "sub": "1234567890", "name": "John Doe", "admin": true }

然后对有效负载进行Base64URL编码形成JSON Web令牌的第二部分

注意,对于签名令牌,此信息虽然受到篡改保护,但是任何人都可以通过解码读取该信息,所以不要将机密信息放到有效载荷中

Signature

要创建签名部分,必须获取编码的标头、编码的有效负载、标头中指定的算法并对其进行签名

例如:

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

签名用于验证消息在此过程中未被更改,并且在使用私钥签名令牌的情况下,可以验证JWT的发件人

1.3.2 JWT登录原理

JWT登录,和上面token机制不同的是,token需要查询数据库或redis验证是否有效,而JWT不用查库,直接在服务端进行校验,因为用户信息及过期时间都在JWT里,只要在服务端进行校验就可以。

优点(和Token比较):

  • 不需要维护session信息,节省资源
  • 不用每次登录都查询数据库或者redis验证token有效性,直接验证JWT

缺点: 因为JWT是无状态的,所以JWT一旦派发出去,如果后端不增加其它逻辑的话,它在失效前都是有效的。这明显不符合我们有些业务场景,比如用户退出登录、账户被封禁删除、权限角色变化等

解决方案:

  • 将JWT存入redis:想让某个JWT失效直接在redis中删除即可,但是这样会导致每次请求都要从redis中查询JWT是否存在的步骤
  • 黑名单机制:和上述方案类似,redis中维护一个黑名单,想让某个jwt失效加入黑名单即可