认证与授权概念

  • 认证:你是谁
  • 授权:你有哪些权限。

    • 即授权在认证之后

      RBAC模型

  • 系统权限控制最常采用的访问控制模型就是 RBAC 模型 。

    • RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。
      • 角色即拥有相同权限的一类用户

        Session-Cookie认证模式

  • 登录验证通过后服务端根据得到的用户信息后创建一个Session存储起来

    • 一般是存储到缓存中
  • 服务器返回给用户Cookie,其中包含了用户信息和SessionID
    • cookie会自动包含在每一个请求中被发送给后端
  • 后续服务器会将cookie中的SessionID与后端保存的Session进行对比以验证身份

    多服务器中实现Session-Cookie

  • 因为不同服务器的Session不共享。所以会导致用户在A服务器登录,但是之后请求其他服务器,就会找不到用户的session而认为他没有登录

  • 有如下解决方案:
    • 通过某种用户的唯一性,将其与特定服务器关联,使得一个用户只会被分配给一个特定的服务器
    • 一个服务器得到Session就把它同步到其他服务器
    • 使用所有服务器都能访问到的数据节点存储session。如缓存

      局限

  1. 不能避免CSRF
  2. 需要手动建立并保存session
  3. 需要浏览器端支持且不禁用cookie
  4. 移动端对cookie的支持不太友好

    Token认证的优劣

  • token是无状态的,即服务端不能主动失效token,必须通知
  • 伪造的非法请求不会携带token,所以token可以避免csrf
  • 链接

    不足的解决

  • 安全问题解决:

    • 构造协议头带httpOnly的cookie,这种cookie不允许浏览器访问,从而避免了xss,但是,这样又导致了你必须自己提供CSRF保护(因为前端还是需要使用某些cookie的)
      • 大部分情况下存放在local storage 下都是最好的选择,某些情况下可能需要存放在标记为httpOnly 的cookie 中会更好。
  • 无状态解决方法:
    • token存储于缓存中,以避免无状态,token修改前端无法及时生效的问题
    • 还可以将失效token存储于一个黑名单中,也能解决无状态问题
    • 还可以使用密匙(没看懂)
    • 还可以设置token的时效
    • 密码修改后token还有效的问题可以使用密码的哈希值对 token 进行签名。因此,如果密码更改,则任何先前的令牌将自动无法验证
  • JWT 最适合的场景是不需要服务端保存用户状态的场景,如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。

    • 即如果服务端要主动取消已认证和授权的信息是做不到,只能等到token到期。而oauth就可以解决无状态的问题

      认证的时效方案

  • Session中一般设置为30分钟,如果如果 30 分钟内用户有访问,就把 session 有效期延长30分钟。

  • token中的方案

    • 类似session,快到期就生成一个新token给前端,如果新旧token不一致则更新前端token。存在问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。
    • 可以每次请求都返回新token,问题是开销大很多
    • 对于安全性不高的系统,可以设置token时效到半夜,从而保证了大部分用户白天可以正常登录
    • 第一个是accessToken ,它的过期时间 token 本身的过期时间比如半个小时,另外一个是refreshToken 它的过期时间更长一点比如为1天。客户端登录后,将 accessToken和refreshToken 保存在本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,如果过期的话,就将 refreshToken 传给服务端。如果有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。该方案的不足是:1) 需要客户端来配合;2) 用户注销的时候需要同时保证两个 token 都无效;3) 重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,提前去通过 refreshToken 获取新的accessToken

      JWT

  • jwt(JSON WEB Token)不需要保存session,只需要返回给客户端一个token即可。jwt相当于token认证的一种是实现方案

  • JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。
  • JWT 由 3 部分构成,每一部分加密后再通过.连接,形成一个?.?.?格式的完整的jwt信息

    1. Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
    2. Payload : 用来存放实际需要传递的数据
      1. 链接
    3. Signature(签名) :服务器通过Payload、Header和一个密钥(secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。

      jwt过程

  • 在基于 Token 进行身份验证的的应用程序中,服务器通过Payload、Header和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端(token中有用户是谁的信息)

  • 客户端将 Token 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求Header都会携带这个令牌。
    • 你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization 字段中:Authorization: Bearer Token
  • 服务器接收请求,检查jwt并从中获取用户信息

    jwt实现认证实战

  • 首先项目里有一个全局拦截器,拦截器拦截一切请求。该拦截器可以实现黑名单,白名单,认证等功能(也可以拆分为多个拦截器)

    • 如果1:token解析成功且2:没有过期(有的项目里是token生成就没有时效信息,解析不出来就直接按照过期处理)同时3:缓存里的登录状态也存在且4:没有过期就放行。否则就拒绝,让用户登录。
      • 注意登录等接口不需要进token的全局拦截器。登录接口就是生成token返回并保存token对应缓存数据(缓存的值一般是用户信息)
      • 请求token过期不管缓存有无过期,直接让用户重新登录。也可以选择token快过期自动生成新token返回,并替换缓存token(用旧token获取缓存键值)。不过这种方式防不了机器人
  • 之后再执行一个拦截器用于存储请求过程中常常使用的数据(当前请求的用户数据)并用于刷新token等操作。
    • 拦截前置增强里如果是已经登录就保存用户数据到ThreadLocal或者往redis里存储。如果token快过期就延长缓存的时效。如果是登录的往缓存里面存入token(服务器)
    • 后置增强是删除ThreadLocal的数据
  • 强制下线的接口是剔除redis的缓存。

    token具体实现

  • 创建token时使用用户名用户iduuid(全局唯一,最好是数字与字母组合的uuid,纯数字可能会重复。有的地方称这个为当前会话用户标识,用户令牌)生成一个token。uuid作为服务端登录状态缓存的key

  • 解析token时可以解析出uuid,uuid可以获取服务端登录状态。
  • token的时效可以设置为12小时。延长时间为2h。距离过期还有2小时就延长。

    1. 该依赖可以根据传入的Map,加密方式,密钥生成token,生成的是永不过期的token貌似
    2. <dependency>
    3. <groupId>io.jsonwebtoken</groupId>
    4. <artifactId>jjwt</artifactId>
    5. <version>0.9.1</version>
    6. </dependency>

    单点登录

  • 即用户登录一个系统中的一个子系统,就有权访问其他相关的子系统。如我们登录jd金融后,也同时登录了京东超市,京东生鲜等

    OAuth2.0

  • OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。即是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 Token,使得第三方应用能够通过该令牌获取相关的资源。

    • OAuth 2.0 是对 OAuth 1.0 的完全重新设计,OAuth 2.0 更快,更容易实现
    • OAuth 1.0 已经被废弃。
  • OAuth 2.0 比较常用的场景就是第三方登录和支付(如微信支付),开发平台(如微信开放平台),当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。
  • OAuth原的理
  • 首先jwt是武装他见,为了实现我有阿金

    Oauth具体实现

    依赖

    <dependency>
        <groupId>org.springframework.security.oauth.boot</groupId>
        <artifactId>spring-security-oauth2-autoconfigure</artifactId>
        <version>2.1.0.RELEASE</version>
      </dependency>