认证与授权概念
- 认证:你是谁
授权:你有哪些权限。
系统权限控制最常采用的访问控制模型就是 RBAC 模型 。
登录验证通过后服务端根据得到的用户信息后创建一个
Session存储起来- 一般是存储到缓存中
- 服务器返回给用户Cookie,其中包含了用户信息和
SessionID- cookie会自动包含在每一个请求中被发送给后端
后续服务器会将cookie中的SessionID与后端保存的
Session进行对比以验证身份多服务器中实现Session-Cookie
因为不同服务器的Session不共享。所以会导致用户在A服务器登录,但是之后请求其他服务器,就会找不到用户的session而认为他没有登录
- 有如下解决方案:
- 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 认证了。
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 获取新的accessTokenJWT
jwt(JSON WEB Token)不需要保存session,只需要返回给客户端一个token即可。jwt相当于token认证的一种是实现方案- JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。
JWT 由 3 部分构成,每一部分加密后再通过
.连接,形成一个?.?.?格式的完整的jwt信息在基于 Token 进行身份验证的的应用程序中,服务器通过Payload、Header和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端(token中有用户是谁的信息)
- 客户端将 Token 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求
Header都会携带这个令牌。- 你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization 字段中:Authorization:
Bearer Token、
- 你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization 字段中:Authorization:
-
jwt实现认证实战
首先项目里有一个全局拦截器,拦截器拦截一切请求。该拦截器可以实现黑名单,白名单,认证等功能(也可以拆分为多个拦截器)
- 如果1:token解析成功且2:没有过期(有的项目里是token生成就没有时效信息,解析不出来就直接按照过期处理)同时3:缓存里的登录状态也存在且4:没有过期就放行。否则就拒绝,让用户登录。
- 注意登录等接口不需要进token的全局拦截器。登录接口就是生成token返回并保存token对应缓存数据(缓存的值一般是用户信息)
- 请求token过期不管缓存有无过期,直接让用户重新登录。也可以选择token快过期自动生成新token返回,并替换缓存token(用旧token获取缓存键值)。不过这种方式防不了机器人
- 如果1:token解析成功且2:没有过期(有的项目里是token生成就没有时效信息,解析不出来就直接按照过期处理)同时3:缓存里的登录状态也存在且4:没有过期就放行。否则就拒绝,让用户登录。
- 之后再执行一个拦截器用于存储请求过程中常常使用的数据(当前请求的用户数据)并用于刷新token等操作。
- 拦截前置增强里如果是已经登录就保存用户数据到ThreadLocal或者往redis里存储。如果token快过期就延长缓存的时效。如果是登录的往缓存里面存入token(服务器)
- 后置增强是删除ThreadLocal的数据
-
token具体实现
创建token时使用
用户名,用户id,uuid(全局唯一,最好是数字与字母组合的uuid,纯数字可能会重复。有的地方称这个为当前会话用户标识,用户令牌)生成一个token。uuid作为服务端登录状态缓存的key- 解析token时可以解析出uuid,uuid可以获取服务端登录状态。
token的时效可以设置为12小时。延长时间为2h。距离过期还有2小时就延长。
该依赖可以根据传入的Map,加密方式,密钥生成token,生成的是永不过期的token貌似<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></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>
