认证方案(session/token/JWT/SSO/OAuth)

1,044 阅读8分钟

一、session

原理:其实就是server自己生成一个sessionId给client。client每次请求都带上,server在自己的内存里找有没有该sessionId对应的HttpSession对象,没有,就返回认证失败,如果有,就拿到用户状态信息,进行下一步操作。

PS:java存内存里,php存文件或者数据库里

存储的HttpSession对象(相关信息),会在超过默认时间没有交互之后,自动销毁,如果想优化的话,就使用js的window.onclose来监视浏览器的关闭动作,然后向服务器发送一个请求来关闭Session。但是常用的就是等它自动销毁

缺点:

  1. 如果用户量在一段时间内非常大, 那给服务器造成的内存压力非常大,占用非常大的内存。
  2. 如果做了负载均衡(多个机器),那么请求可能到了一台没有sessionID的机器,造成session丢失
  3. 存在安全问题,CSRF跨站伪造请求攻击,cookie可能被截获

session是基于cookie实现的,sessionId存在其他地方也可以,请求的时候在指定的位置带上就可以,给到服务端校验。session存在服务器,sessionId被cookie存在客户端

SessionID 是连接 Cookie 和 Session 的一道桥梁

image.png

二、Token

原理:是在用户输入账号密码校验通过的时候,服务器下发一个token,以后每次浏览器请求都带上token,服务器进行校验,成功了,就返回对应的数据信息。

1.access token

Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。

image.png

2、refresh token

Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。

image.png

3、token的组成

header密文,payload密文,签名;header、 payload使用base64分别加密,再合起来,使用密钥和HS256加密生成签名,放后面

token = base64(header).base64(payload).HS256(密钥,base64(header).base64(payload))

4、token的校验

  1. 服务端使用原来的秘钥与密文(header密文+"."+payload密文)同样进行HS256运算,然后用生成的签名与token携带的签名进行对比,若一致说明token合法,不一致说明原文被修改。
  2. 判断是否过期,客户端通过用Base64解密第二部分(payload密文),可以知道荷载中授权时间,以及有效期。通过这个与当前时间对比发现token是否过期。

image.png

eyJhbGciOiJIUzI1NiJ9. 
eyJnbG9iYWxfdXNlcl9pZCI6MTk3OSwiZ2xvYmFsX3VzZXJfbmFtZSI6Iui1teS4ueWugSIsImV4cCI6MTYyODQyNzY0N30.
HUPgAksi_nN3uc9UOlQ8_tvQQotNPEuLh3edlxgzZm8

三、JWT(Json Web Token)

  • header (base64后的): { 'typ': 'JWT', 'alg': 'HS256' }
  • payload (base64后的)
  • secret

需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret(私钥)组合加密,然后就构成了jwt的第三部分

PS:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去

原理:jwt的token由3部分组成(如上),验证的过程是每次请求,获取到token,拿出前两部分解析,经过加盐私钥用header声明的加密算法生成签名,跟第三部分对比,一样就算验证通过,再拿到token中的用户信息,去进行下一步操作。不一样就返回认证失败

image.png

优点:

  1. 可扩展性好,不像session需要多机数据共享(内存或者redis)
  2. 无状态

缺点:

  1. 不安全,base64编码大家都知道
  2. 性能:如果payload的很大(可能有信息交换),经过base64编码后会非常大,cookie的4k内存可能存不下,就得放storage里,每次请求的时候都放header里,导致header比body还大,所以可能要比session的开销还大
  3. 一次性,无法废弃:我后来想在jwt的payload里加个字段或改一下值,所以签发了新的jwt,但是旧的还没过期,使用旧的jwt获取的是过期的payload。所以需要额外加个过期jwt的黑名单,避免使用过时的 4.续签:

第一种:每次请求都签发新的JWT,暴力且不优雅

第二种:需要在redis存上jwt的过期时间,每次请求,都刷新一下该jwt的过期时间,但是就是有状态的了,跟session差不多了。

适用场景:有效期短或者只有一次,比如邮箱链接账户激活

四、Token和JWT的区别

  1. Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。
  2. JWT:用户的信息第二部分 Payload加密后和第三部分签名里都有,存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。就是服务端校验通过后,选择直接使用请求端给到的用户信息进行数据返回

五、SSO(Single Sign On)单点登录

意思就是把多于一个产品的用户登录逻辑抽离出来,达到只输入一次用户名和密码就能同时登录多个产品的效果

1、同域

登录

image.png

登出

image.png

区分系统:可以使用二级域名区分不同的系统,写入cookie在一级域名下,就比如【.songguo7.com】

2、不同域 CAS(Center Authentication Service)中心授权服务

SSO是一种设计,而CAS是实现它的方式其中之一,如果是同域名或者同父域可以使用session | token进行认证,但是跨域的情况下,多个产品不同域名,需要CAS实现认证。

登录

image.png

术语:

  1. TGT(T icket Grangting Ticket):存储在全局session中,集成用户信息和ST
  2. TGC(Ticket Grangting Cookie):存储在浏览器的cookie,就是TGT Session的标识(SessionID)可以理解为key,value是TGT
  3. ST(ServiceTicket):根据TGT生成,给到网站的

流程

  1. 我(浏览器)想看看A网站,但是A网站说我没登录
  2. 给我定向到认证中心,把A网站的地址作为参数放地址后面

www.cas-server.com/login?href=…

  1. SSO也说我没登录,因为我没有TGC,他里面也没有我的TGT,引导我到SSO的登录页面

  2. 我输入用户名+密码提交登录申请

  3. 认证中心验证成功,生成TGT,创建全局session,并把TGT存进去,创建TGC(存入浏览器cookie),重定向到A网站带着ST(令牌)放在请求地址后面作为参数

www.a.com?ticket=ST-25939-sqbDVZcuSvrvBC6MQlg5

  1. A网站拿到ST令牌去认证中心验证是不是它给的

  2. 验证通过,A网站拿着这个令牌创建了我与A网站的局部回话(session),返回受保护资源

  3. 我又想看看B网站,B网站看我没登录

  4. B网站把自己的地址作为参数,跳到认证中心

  5. 认证中心看到有TGC,并且有效,就生成一个新的ST给B网站

  6. B网站拿着令牌到认证中心验证

  7. 令牌有效,B网站也跟我建立了局部会话

  8. 返回受保护资源

注销

image.png

流程:

  1. 我在A网站发起注销申请

  2. A网站拿到ST令牌,带着令牌向认证中心发起注销申请

  3. 认证中心校验令牌有效性

  4. 注销全局会话

  5. 向各个子系统发起注销请求

  6. 子系统接收认证中心注销请求,销毁局部会话

  7. 再访问就引导至登录界面

六、OAuth2.0(授权)

image.png

这就叫做 OAuth 2.0 协议

你进行第三方授权时(文中的QQ),用户名和密码是不经过目标服务器的(文中的豆瓣),这保证了授权的安全性

第三方授权服务器只给目标服务器返回有时效性的 code 和 token,目标服务器通过这个去第三方资源服务器,换取用户信息,这达成了拿到用户信息的目的。

所以总的来说,oauth 协议,就是由于三者(用户、目标、第三方)相互不信任,又想使用第三方服务器的授权功能,以及获取第三方服务器存储的用户信息,而产生的一个办法。

七、参考文档

  1. blog.csdn.net/coderising/…

  2. blog.csdn.net/coderising/…

  3. 查阅的资料很多,有点记不过来了,大家可以查缺补漏,指正错误~,没写上的,可以找到我加在参考文档里哈