02 微服务应用的认证与授权

1 用户认证与授权

1-1认证授权的基础知识

UAA:User Account and Authentication。

认证定义:判断一个用户的身份是否合法的过程

常见的认证方式

1) 用户名密码登录
2) 二维码登录
3) 手机短信登录
4) 指纹认证

授权定义:根据用户的权限授予用户访问的资源(授权是在用户认证之后)

1-1-1 认证的实现方式:会话

会话机制:系统为了保持当前用户的登录状态所提供的机制

会话机制的实现手段

1)基于session方式
2)基于token方式

1-1-2 基于session的认证机制

基于session的认证流程(session_id)

1)用户首次认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的sesssion_id 存放到 cookie 
2)用户客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户的合法校验
3)当用户退出系统或session过期销毁时,客户端的session_id也就无效了。

1-1-3 基于token的认证机制

1)用户认证成功后,服务端生成一个token发给客户端
2)客户端存储token,每次请求时带上token
3) 服务端收到token通过验证后即可确认用户身份。

问题:基于session的认证机制与基于token的认证机制的本质区别?

实现机制上

  • session的认证方式由Servlet规范定制,服务端要维护session信息,客户端需要cookie
  • token的认证机制不需要服务端存储token,并且不限制客户端的存储方式 ,用户的身份信息交给专门的服务管理

本质区别:session的认证方法使用上限制比较大

共同之处:都需要服务端分配给客户端一个唯一标识

实际应用:目前项目都需要前后端分离,因此通常采用token的方式实现用户认证

1-2 分布式认证的特点

特点1:分布式统一认证

基本思想:采用独立的认证服务来处理系统认证授权的请求

1) 前端请求UAA认证服务请求认证,认证通过返回Token
2) 前端携带Token访问各应用。
特点2:开发认证体系(支持第三方)

基本思想:不仅服务于平台自身,以开放API的方式供第三方应用接入

1)第三方应用请求UAA认证服务请求认证,认证通过获取Token。
2)第三方应用携带Token访问API代理(专门针对第三方应用接入开发的微服务)。
3)API代理访问平台微服务向第三方应用返回业务数据

1-3 session与token的分布式认证实现

1-3-1 基本session的分布式认证机制

特点:每个应用服务都需要在session中存储用户身份信息,通过负载均衡将本地的请求分配到另一个应用服务需要将session信息带过去,否则会重新认证

核心问题:session信息该如何同步,从而避免不必要的重复认证

session信息同步的常见做法

1)Session复制:多台应用服务器之间同步session,使session保持一致,对外透明。
2)Session黏贴:当用户访问集群中某台服务器后,强制指定后续所有请求均落到此机器上
3)Session集中存储:将Session存入分布式缓存中,所有服务器应用实例统一从分布式缓存中存取Session(信息的同步交给分布式缓存处理)

session分布式认证的特点

优点

  • 在服务端对会话进行控制,且安全性较高

缺点

  • 基于cookie,不适合移动端,且无法跨域,横向扩展需考虑session的容错性

跨域问题

Springboot处理CORS跨域请求的三种方法

  • 正向代理(跨区域访问)代理的对象是客户端,反向代理(ngnix负载均衡)代理的对象是服务端

1-3-2 基于token的分布式认证机制

优点:服务端不用存储认证数据,易维护扩展性强, 客户端可以把token 存在任意地方,并且可以实现web和app统一认证机制

为什么基于token的方式服务端不需要存储认证数据?

缺点

  • token由于自包含信息,因此一般数据量较大 ,占用带宽????????????????
  • token的签名信息验证CPU开销较大
问题:为什么采用基于token的分布式认证方式?
1、适合统一认证的机制,客户端、一方应用、三方应用都遵循一致的认证机制。
2、token认证方式对第三方应用接入更适合,因为它更开放,使用当前有流行的开放协议Oauth2.0、JWT。
3、一般情况服务端无需存储会话信息,减轻了服务端的压力

1-4 基于token分布式认证的方案具体实现

流程

(1)接入方(需要使用平台资源的统称为接入方)采取OAuth2.0方式请求统一认证服务(UAA)进行认证。
(2)认证服务(UAA)调用统一账号服务去查询该用户信息及其权限信息。(第三方应用接入不需要该步骤)
(3)认证服务(UAA)验证登录用户及第三方应用合法性。
(4)若接入方身份合法,认证服务生成jwt令牌返回给接入方,其中jwt中包含了权限信息。
(5)接入方携带jwt令牌对API网关内的微服务资源进行访问。
(6)API网关对令牌解析、并验证接入方的权限是否能够访问本次请求的微服务。
(7)如果接入方的权限没问题,API网关将Token转发至微服务。
(8)微服务收到请求,明文token中包含登录用户的身份和权限信息,后续微服务使用用户身份及权限信息
UAA:User Account and Authentication(用户身份与认证)
JWT:Json web token 
     为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

user服务、UAA服务、网关服务这三个组件职责如下

1)统一账号服务
提供商户和平台运营人员的登录账号、密码、角色、权限、资源等系统级信息的管理,不包含用户业务信息。
2)统一认证服务(UAA)
它承载了OAuth2.0接入方认证、登入用户的认证、授权以及生成令牌的职责,完成实际的用户认证、授权功能。
3)API网关
作为系统的唯一入口,API网关为接入方提供定制的API集合,它可能还具有其它职责,如身份验证、监控、负载
均衡、缓存等。API网关方式的核心要点是,所有的接入方和消费端都通过统一的网关接入微服务,在网关层处理
所有的非业务功能

注意:上面3个服务都没有业务相关的信息,因此可以用于各种分布式系统

2 OAuth2认证

2-1 基本流程

OAuth(开放授权)定义:是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容

2-1-1 采用微信登录第三方P站的实例

  • P站需要成功从微信获取用户的身份信息则认为用户认证成功
A) 用户扫描二维码即资源拥有者发送请求微信服务给P站授权
B) 微信服务会对资源拥有者的身份进行验证, 验证通过后,微信会询问用户是否给授权P站访问自己的微信数据(防止CSRF攻击)
C) 用户点击“确认登录”表示同意授权
D) 微信认证服务器会颁发一个授权码,并重定向到P站(第三方应用)
E) P站携带token请求访问用户的微信资源
F) 微信服务校验token并提供资源
用户 第三方应用 微信认证与授权服务 微信用户信息

2-1-2 OAauth2.0认证的角色

1、客户端
本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源,比如:Android客户端、Web客户端(浏览器端)、微信客户端等
2、资源拥有者
通常为用户,也可以是应用程序,即该资源的拥有者。
3、授权服务器(也称认证服务器)
用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌
(access_token),作为客户端访问资源服务器的凭据。本例为微信的认证服务器。
4.存储资源的服务器,本例子为微信存储的用户信息
问题:为什么OAuth的授权码进行两次认证(客户端,资源拥有者)?
1)两次认证的目的不同,第一次认证是对请求访问资源的客户端(携带client_id:客户端标识 client_secret:客户端秘钥)进行认证,防止非法分子
第二次认证是对资源拥有者进行认证,即对用户本身进行认证。
实例:某用户尝试用微信登录非法网站,显然在OAuth认证中第一次认证就无法通过
2)两次认证可以在第三方登录时对CSRF攻击进行有效防护。

OAuth的官方资料

2-2 Oauth的四种模式

authorization: 授权码

四种模式的区别:客户端获取token的执行流程不同,适用于不同的场景

模式 特点 安全性 使用场景 授权类型(grant_type)
授权码模式 access token仅在服务端进行交换 用于Web服务器端应用或第三方的原生App调用资源服务 Authorization(authorization_code)
密码模式 access token会给客户端 第一方的单页面应用以及第一方的原生App(有密码) password
客户端模式 需要对客户端完全信任 非常信任的客户端应用 client_credentials
简化模式(授权码模式简化) access token会给客户端(去除授权码) 简化模式用于第三方单页面应用 implicit

2-2-1 授权码模式的执行步骤

  • step1:资源拥有者打开客户端,点击第三方登录,它将浏览器被重定向到授权服务器,重定向时会附加客户端的身份信息

=======================================================================================================
重定向URL实例:/uaa/oauth/authorize?client_id=p2pweb&response_type=code&scope=app&redirect_uri=http://xx.xx/notify
参数列表如下:
client_id:客户端接入标识。
response_type:授权码模式固定为code。
scope:客户端权限。
redirect_uri:跳转uri,当授权码申请成功后会跳转到此地址,并在后边带上code参数(授权码)
  • step2:授权服务器验证客户端身份后,请求用户授权,此时浏览器出现向授权服务器授权页面,之后将用户同意授权(页面跳转出询问是否允许登录微信)
  • step3:授权服务器将授权码(AuthorizationCode)****转经浏览器发送给client(通过redirect_uri)。
  • step4:客户端拿着授权码向授权服务器索要访问access_token,请求如下 ,授权服务器返回令牌(access_token)
/uaa/oauth/token?client_id=p2pweb&client_secret=gdjbcd&grant_type=authorization_code&code=5PgfcD&redirect_uri=htt
p://xx.xx/notify

参数列表如下
client_id:客户端准入标识。
client_secret:客户端秘钥。
grant_type:授权类型,填写authorization_code,表示授权码模式
code:授权码,就是刚刚获取的授权码,注意:授权码只使用一次就无效了,需要重新申请。
redirect_uri:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。

授权码模式特点:

这种模式是四种模式中最安全的一种模式。一般用于Web服务器端应用或第三方的原生App调用资源服务的时候。
因为在这种模式中access_token不会经过浏览器或移动端的App,而是直接从服务端去交换,这样就最大限度的减
小了令牌泄漏的风险

2-2-2 密码模式执行步骤

step1:资源拥有者将用户名、密码发送给客户端

step2:客户端拿着资源拥有者的用户名、密码向授权服务器请求令牌(access_token)

/uaa/oauth/token?client_id=p2pweb&client_secret=fgsdgrf&grant_type=password&username=shangsan&password=123456
上面链接只是表明传递哪些参数,实际传输密码不可能是明文传输的
参数列表如下:
client_id:客户端准入标识。
client_secret:客户端秘钥。
grant_type:授权类型,填写password表示密码模式
username:资源拥有者用户名。
password:资源拥有者密码。

step3:授权服务器将令牌(access_token)发送给client

密码模式特点

安全性:直接将用户敏感信息泄漏给了client,因此这就说明这种模式只能用于client是我们自己开发的情况下。
应用场景:因此密码模式一般用于我们自己开发的,第一方原生App或第一方单页面应用。

2-2-3 客户端模式的执行步骤

(1)客户端向授权服务器发送自己的身份信息,并请求令牌(access_token)
(2)确认客户端身份无误后,将令牌(access_token)发送给client
/uaa/oauth/token?client_id=p2pweb&client_secret=fdafdag&grant_type=client_credentials
client_id:客户端准入标识。
client_secret:客户端秘钥。
grant_type:授权类型,填写client_credentials表示客户端模式

特点:最方便但最不安全的模式。因此这就要求我们对client完全的信任,而client本身也是安全的。

应用场景:这种模式一般用来提供给我们完全信任的服务器端服务。比如,合作方系统对接,拉取一组用户信息。客户端模式适应于没有用户参与的,完全信任的一方或合作方服务器端程序接入

2-2-4 简化模式执行步骤

  • step1:资源拥有者打开客户端,客户端要求资源拥有者给予授权,它将浏览器被重定向到授权服务器,重定向时会附加客户端的身份信息
/uaa/oauth/authorize?client_id=p2pweb&response_type=token&scope=app&redirect_uri=http://xx.xx/notify
参数描述同授权码模式 ,注意response_type=token,说明是简化模式。
  • step2:浏览器出现向授权服务器授权页面,之后将用户同意授权。

  • step3:授权服务器将授权码将令牌(access_token)以Hash的形式存放在重定向uri的fargment中发送给浏览器。

fragment 主要是用来标识 URI 所标识资源里的某个资源,在 URI 的末尾通过 (#)作为 fragment 的开头,
其中 # 不属于 fragment 的值。如https://domain/index#L18这个 URI 中 L18 就是 fragment 的值。大家只需要
知道js通过响应浏览器地址栏变化的方式能获取到fragment 就行了

2-3 JWT的概念

JSON Web Token(JWT)定义:一种简洁的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改

组成

Header PayLoad Signature
令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA) json对象,它是存放有效信息的地方 签名,此部分用于防止jwt内容被篡改

2-4 UAA的密码模式测试(spring security+oauth2.0)

认证服务返回的结果

{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhbmp1LXJlc291cmNlIl0sInBheWxvYWQiOnsiNCI6eyJyZXNvdXJjZXMiOm51bGwsInVzZXJfYXV0aG9yaXRpZXMiOnsicl8wMDEiOlsic2pfbV9jb25zb2xlIiwic2pfbV9hcHBfbGlzdCIsInNqX21fdHJhbnNhY3Rpb25fbGlzdCIsInNqX21fYWNjb3VudF9jaGVjayIsInNqX21fcGF5bWVudCIsInNqX21fYWNjb3VudF9saXN0Iiwic2pfbV9lbnRlcnByaXNlX2F1dGgiLCJzal9tX3N0b3JlX2xpc3QiLCJzal9tX3N0YWZmX2xpc3QiLCJzal9vX21lbWJlcl9saXN0Iiwic2pfb19lbnRyZXByaXNlX2xpc3QiLCJzal9vX2F1ZGl0Iiwic2pfb19zZXJ2aWNlX3R5cGUiLCJzal9vX2FjY291bnRfY2hlY2siLCJzal9vX2FkbWluX2xpc3QiLCJzal9vX3JvbGVfbGlzdCIsInNqX21fYXBwX2NyZWF0ZSIsInNqX21fcGF5bWVudF9zZXQiLCJzal9tX3N0b3JlX2NyZWF0ZSIsInNqX21fc3RvcmVfcXVlcnkiLCJzal9tX3N0YWZmX2NyZWF0ZSIsInNqX21fc3RhZmZfcXVlcnkiLCJzal9vX21lbWJlcl9xdWVyeSIsInNqX29fZW50ZXJwcmlzZV9xdWVyeSIsInNqX29fZW50ZXJwcmlzZV9jcmVhdGUiLCJzal9vX3NlcnZpY2VfY3JlYXRlIiwic2pfb19zZXJ2aWNlX3F1ZXJ5Iiwic2pfb19hZG1pbl9jcmVhdGUiLCJzal9vX2FkbWluX3F1ZXJ5Iiwic2pfb19yb2xlX2NyZWF0ZSIsInNqX29fcm9sZV9xdWVyeSIsInNqX29fcm9sZV9zYXZlIiwic2pfbV9hdXRoX2FwcGx5Iiwic2pfbV9jb25zb2xlX3JlbmV3Iiwic2pfbV9jb25zb2xlX3VwZ3JhZGUiLCJzal9tX2FwcF9zYXZlIiwic2pfbV9hcHBfbW9kaWZ5Iiwic2pfbV9wYXlwYXJhbV9zYXZlIiwic2pfbV9wYXlfc2V0Iiwic2pfbV9wYXlfc2F2ZSIsInNqX21fYzJiX3FyY29kZSIsInNqX21fYjJjX29yZGVyIiwic2pfbV9oNV92aWV3Iiwic2pfbV9idW5kbGVfYnV5Iiwic2pfbV9lbnRlcnByaXNlX2luZm9fc3VibWl0Iiwic2pfbV9lbnRlcnByaXNlX2luZm9fY2FuY2VsIiwic2pfb19lbnRlcnByaXNlX2F1dGhfcGFzcyIsInNqX29fZW50ZXJwcmlzZV9hdXRoX3JlamVjdGlvbiIsInNqX21fc3RvcmVfZWRpdCIsInNqX21fc3RhZmZfZWRpdCIsInNqX29fYWRtaW5fZWRpdCIsInNqX29fcm9sZV9lZGl0Iiwic2pfbV9zdG9yZV9zYXZlIiwic2pfbV9zdG9yZV9kZWwiLCJzal9tX3N0YWZmX3NhdmUiXSwicl8wMDIiOlsic2pfbV90cmFuc2FjdGlvbl9saXN0Iiwic2pfbV9hY2NvdW50X2NoZWNrIl19fX0sInVzZXJfbmFtZSI6InRlc3QiLCJzY29wZSI6WyJyZWFkIl0sIm1vYmlsZSI6IjEzNzczMzI1OTcwIiwiZXhwIjoxNjU5MTU3NjYzLCJjbGllbnRfYXV0aG9yaXRpZXMiOlsiUk9MRV9NRVJDSEFOVCIsIlJPTEVfVVNFUiJdLCJqdGkiOiJmNzNmYzA1ZC1mNTQzLTQ5OTItOTdiMS0yMTE3NDJhN2IwYjYiLCJjbGllbnRfaWQiOiJtZXJjaGFudC1wbGF0Zm9ybSJ9.bnmkfJ6lDx6Q6szNf2M_dNHHL42jW9_K9ITrEGZBy5U",  
// 访问token,密码模式下客户端拿到该token向授权服务获取用户权限信息
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic2hhbmp1LXJlc291cmNlIl0sInBheWxvYWQiOnsiNCI6eyJyZXNvdXJjZXMiOm51bGwsInVzZXJfYXV0aG9yaXRpZXMiOnsicl8wMDEiOlsic2pfbV9jb25zb2xlIiwic2pfbV9hcHBfbGlzdCIsInNqX21fdHJhbnNhY3Rpb25fbGlzdCIsInNqX21fYWNjb3VudF9jaGVjayIsInNqX21fcGF5bWVudCIsInNqX21fYWNjb3VudF9saXN0Iiwic2pfbV9lbnRlcnByaXNlX2F1dGgiLCJzal9tX3N0b3JlX2xpc3QiLCJzal9tX3N0YWZmX2xpc3QiLCJzal9vX21lbWJlcl9saXN0Iiwic2pfb19lbnRyZXByaXNlX2xpc3QiLCJzal9vX2F1ZGl0Iiwic2pfb19zZXJ2aWNlX3R5cGUiLCJzal9vX2FjY291bnRfY2hlY2siLCJzal9vX2FkbWluX2xpc3QiLCJzal9vX3JvbGVfbGlzdCIsInNqX21fYXBwX2NyZWF0ZSIsInNqX21fcGF5bWVudF9zZXQiLCJzal9tX3N0b3JlX2NyZWF0ZSIsInNqX21fc3RvcmVfcXVlcnkiLCJzal9tX3N0YWZmX2NyZWF0ZSIsInNqX21fc3RhZmZfcXVlcnkiLCJzal9vX21lbWJlcl9xdWVyeSIsInNqX29fZW50ZXJwcmlzZV9xdWVyeSIsInNqX29fZW50ZXJwcmlzZV9jcmVhdGUiLCJzal9vX3NlcnZpY2VfY3JlYXRlIiwic2pfb19zZXJ2aWNlX3F1ZXJ5Iiwic2pfb19hZG1pbl9jcmVhdGUiLCJzal9vX2FkbWluX3F1ZXJ5Iiwic2pfb19yb2xlX2NyZWF0ZSIsInNqX29fcm9sZV9xdWVyeSIsInNqX29fcm9sZV9zYXZlIiwic2pfbV9hdXRoX2FwcGx5Iiwic2pfbV9jb25zb2xlX3JlbmV3Iiwic2pfbV9jb25zb2xlX3VwZ3JhZGUiLCJzal9tX2FwcF9zYXZlIiwic2pfbV9hcHBfbW9kaWZ5Iiwic2pfbV9wYXlwYXJhbV9zYXZlIiwic2pfbV9wYXlfc2V0Iiwic2pfbV9wYXlfc2F2ZSIsInNqX21fYzJiX3FyY29kZSIsInNqX21fYjJjX29yZGVyIiwic2pfbV9oNV92aWV3Iiwic2pfbV9idW5kbGVfYnV5Iiwic2pfbV9lbnRlcnByaXNlX2luZm9fc3VibWl0Iiwic2pfbV9lbnRlcnByaXNlX2luZm9fY2FuY2VsIiwic2pfb19lbnRlcnByaXNlX2F1dGhfcGFzcyIsInNqX29fZW50ZXJwcmlzZV9hdXRoX3JlamVjdGlvbiIsInNqX21fc3RvcmVfZWRpdCIsInNqX21fc3RhZmZfZWRpdCIsInNqX29fYWRtaW5fZWRpdCIsInNqX29fcm9sZV9lZGl0Iiwic2pfbV9zdG9yZV9zYXZlIiwic2pfbV9zdG9yZV9kZWwiLCJzal9tX3N0YWZmX3NhdmUiXSwicl8wMDIiOlsic2pfbV90cmFuc2FjdGlvbl9saXN0Iiwic2pfbV9hY2NvdW50X2NoZWNrIl19fX0sInVzZXJfbmFtZSI6InRlc3QiLCJzY29wZSI6WyJyZWFkIl0sImF0aSI6ImY3M2ZjMDVkLWY1NDMtNDk5Mi05N2IxLTIxMTc0MmE3YjBiNiIsIm1vYmlsZSI6IjEzNzczMzI1OTcwIiwiZXhwIjoxNjI3ODgwODYzLCJjbGllbnRfYXV0aG9yaXRpZXMiOlsiUk9MRV9NRVJDSEFOVCIsIlJPTEVfVVNFUiJdLCJqdGkiOiJmY2NkMDBkYy1jMzhkLTRjNjEtYmEzZC00YmUwNGVmOTMzNmMiLCJjbGllbnRfaWQiOiJtZXJjaGFudC1wbGF0Zm9ybSJ9.wi2LK281j5CZ2aPkhaZkA1w-n7zODY3nGmp3JU2I_NE",                           // 刷新的token               
    "expires_in": 31535999,                     // token的过期时间
    "scope": "read",                            // token的权限
    "jti": "f73fc05d-f543-4992-97b1-211742a7b0b6"  // token的唯一标识
}

使用access_token从认证服务器那边获取用户的身份与授权信息

{
    "aud": [
        "shanju-resource"
    ],
    "payload": {                                //应用名称
        "4": {
            "resources": null,
            "user_authorities": {               //用户权限
                "r_001": [         
                    "sj_m_console",
                    "sj_m_app_list",
                    "sj_m_transaction_list",
                    "sj_m_account_check",
                    "sj_m_payment",
                    "sj_m_account_list",
                    "sj_m_enterprise_auth",
                    "sj_m_store_list",
                    "sj_m_staff_list",
                    "sj_o_member_list",
                    "sj_o_entreprise_list",
                    "sj_o_audit",
                    "sj_o_service_type",
                    "sj_o_account_check",
                    "sj_o_admin_list",
                    "sj_o_role_list",
                    "sj_m_app_create",
                    "sj_m_payment_set",
                    "sj_m_store_create",
                    "sj_m_store_query",
                    "sj_m_staff_create",
                    "sj_m_staff_query",
                    "sj_o_member_query",
                    "sj_o_enterprise_query",
                    "sj_o_enterprise_create",
                    "sj_o_service_create",
                    "sj_o_service_query",
                    "sj_o_admin_create",
                    "sj_o_admin_query",
                    "sj_o_role_create",
                    "sj_o_role_query",
                    "sj_o_role_save",
                    "sj_m_auth_apply",
                    "sj_m_console_renew",
                    "sj_m_console_upgrade",
                    "sj_m_app_save",
                    "sj_m_app_modify",
                    "sj_m_payparam_save",
                    "sj_m_pay_set",
                    "sj_m_pay_save",
                    "sj_m_c2b_qrcode",
                    "sj_m_b2c_order",
                    "sj_m_h5_view",
                    "sj_m_bundle_buy",
                    "sj_m_enterprise_info_submit",
                    "sj_m_enterprise_info_cancel",
                    "sj_o_enterprise_auth_pass",
                    "sj_o_enterprise_auth_rejection",
                    "sj_m_store_edit",
                    "sj_m_staff_edit",
                    "sj_o_admin_edit",
                    "sj_o_role_edit",
                    "sj_m_store_save",
                    "sj_m_store_del",
                    "sj_m_staff_save"
                ],
                "r_002": [
                    "sj_m_transaction_list",
                    "sj_m_account_check"
                ]
            }
        }
    },
    "user_name": "test",                            // 用户名称
    "scope": [
        "read"
    ],
    "mobile": "13773325970",                        // 用户手机号
    "exp": 1659157663,
    "client_authorities": [                         // 客户端
        "ROLE_MERCHANT",
        "ROLE_USER"
    ],
    "jti": "f73fc05d-f543-4992-97b1-211742a7b0b6", 
    "client_id": "merchant-platform"
}
问题:为什么已经设置了access_token还另外设置refresh token?
access_token是有时效性的,我们希望在用户在线的的时候access_token不会失效。
粗暴策略:用户的每次请求都去延长token的有效期,这样对服务端的压力比较大
好的策略:用户每次登录成功后,除了分配access_token,此外另外分配一个refresh token,客户端定时调用refresh token去延长access token有效期(或者说返回新的的access token)
前后端分离跨域访问解决策略
1.nginx反向代理,纯前端解决跨域问题(前端项目将第三方的接口地址映射成本地的地址,前端只要调用本地的地址,就可以请求到第三方的数据了,比如,nginx提供的反向代理服务就很稳定)
2.webservice调用第三方服务,提供本地前端接口,解决跨域问题。(后台提供统一http调用接口,避免跨域的产生)
3.服务导入jar包依赖,纯后端解决跨域问题(java-property-utils-1.9.jar和cors-filter-1.7.jar)。

参考资料

01 Spring Security 分布式系统认证方案
02 支付项目开源实现
03 分布式OAuth2.0认证

原文地址:https://www.cnblogs.com/kfcuj/p/15079446.html