UAA服务指南
1.认证与授权
1.1.用户认证与授权(面试)
在操作系统中,少不了的操作就是用户的登录了。对于系统来说就是要校验用户的信息是否合法,并是否有能力做某事。这要行为称之为 认证 和 授权。
认证 :用户认证即用户去访问系统资源时系统要求验证用户的身份信息,身份合法方可继续访问。常见的用户身份认证表现形式有:用户名密码登录,二维码登录,手机短信登录,指纹认证等方式。
授权: 用户认证通过后去访问系统的资源,系统会判断用户是否拥有访问资源的权限,只允许访问有权限的系统资源,没有权限的资源将无法访问,这个过程叫用户授权。
下面我们主要讨论用户认证相关内容。
1.2.用户认证机制(面试)
用户认证表面上看只是系统校验用户名(身份)、密码(凭证)的过程。但是,为了会话保持,为了提高安全性,为了适应不同系统架构以及千奇百怪的认证方式(用户名、密码,二维码,短信,三方认证,单点登录),认证的机制也在不断演进。
1.2.1.基于session认证
目前大多数web应用的用户认证机制都是基于session的。用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话),而发给客户端 sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户的合法校验。当用户登出或过期服务端session销毁,客户端的session_id也就无效了。
总体来讲,基于session认证的认证方式,可以更好的在服务端对会话进行控制,且安全性较高。但是,session机制方式基于cookie,在移动应用上无法有效使用,并且无法跨域,对服务器的压力大。
1.2.2.基于Token认证
随着 Restful API、微服务的兴起,基于 Token 的认证现在已经越来越普遍。基于token的用户认证是一种服务端无状态的认证方式,所谓服务端无状态指的token本身包含所有的登陆用户相关数据,而客户端在认证后的每次请求都会携带token,因此服务器端无需存放token数据。
交互机制:
当用户认证后,服务端生成一个token发给客户端,客户端可以放到 cookie 或 localStorage 等存储中,每次请求时带上 token,服务端收到token通过验证后即可确认用户身份。
1.2.3.1 OAuth 2.0认证
OAuth 就是基于 token 认证实现的认证协议。
OAuth(开放授权)是一个开放标准,允许用户授权第三方应用可以访问存储在服务提供者上的信息,而不需要将用户名和密码提供给第三方应用。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。
Oauth协议目前发展到2.0版本,1.0版本过于复杂,2.0版本已得到广泛应用,所有课程中只会介绍 Oauth 2.0 内容。
OAuth2.0正是实现了上面的机制,它的运行流程如下:
(A)张三打开BBS的APP,并使用新闻门户账号登录,BBS要求张三授权基本用户信息及喜好数据。
(B)张三同意给予BBS授权。
(C)客户端使用上一步获得的授权,向新闻门户的认证服务器申请令牌(access_token)。
(D)认证服务器对BBS客户端进行认证以后,确认无误,同意发放令牌(access_token)。
(E)BBS客户端使用令牌,向新闻门户的资源服务器申请获取基本用户信息及喜好数据这些资源。
(F)新闻门户的资源服务器确认令牌(access_token)无误,同意向BBS开放资源。
通过上面流程我们了解到OAuth2.0有以下角色:
●客户端(Client):第三方应用,本身不存储资源,需要通过资源拥有者的授权去请求资源服务器的资源。本例中指的是BBS
●资源拥有者(Resource Owner):通常为用户,也可以是应用程序,即该资源的拥有者。本例指的是张三。
●授权服务器(Authorization Server 也称认证服务器):用于服务提供商对资源拥有的身份进行认证、对访问资源进行授权,认证成功后会给客户端发放令牌(access_token),作为客户端访问资源服务器的凭据。本例指的是新闻门户用于提供OAuth2.0开放机制,而专门搭建的认证服务器。
●资源服务器(Resource Server):服务提供商存储用户生成的资源的服务器。本例指的是新闻门户用于存放用户数据的服务器。
现在还有一个问题,服务提供商能允许随便一个客户端就接入到它的授权服务器吗?答案是否定的,服务提供商会给准入的接入方一个身份,用于接入时的凭据:
client_id:客户端标识
client_secret:客户端秘钥
因此,准确来说,授权服务器对两种OAuth2.0中的两个角色进行认证授权,分别是资源拥有者、客户端。
2.认证体系设计
UAA 认证体系结构图
流程描述:
(1)用户登录通过接入方(目前指前端)在学成在线登录,接入方采取OAuth2.0 密码模式请求认证服务(UAA)。
(2)认证服务(UAA)调用统一账号服务去验证该用户,并获取用户权限信息。
(3)认证服务(UAA)获取接入方权限信息,并验证接入方是否合法,。
(4)若登录用户以及接入方都合法,生成令牌返回给接入方,其中包含了用户权限及接入方权限。
(5)后续,接入方携带令牌对学成在线微服务资源进行访问。
(6)API网关对令牌解析、并验证接入方的权限是否能够访问本次请求的微服务。
(6)网关校验通过后,就可以访问学成在线后端资源服务。
流程 红色图框 所涉及到统一账号服务、UAA服务、API网关这三个组件,因此下面介绍三个组件的职责。
UAA(统一认证服务):UAA组件之一,它承载了OAuth2.0接入方认证、登入用户的认证、授权以及生成令牌的职责,并连接“统一账号服务”,完成实际的用户认证、授权功能。
统一账号服务:UAA组件之一,提供门户、教育机构和平台运营人员的登录账号、密码、角色、权限、资源等系统级信息的管理,不包含用户业务信息。
API网关:UAA组件之一,实现接入客户端权限拦截、令牌解析并转发当前登录用户信息(jsonToken)给业务微服务,这样下游微服务就不需要关心令牌格式解析以及OAuth2.0相关机制了,它将作为之前网关的替代物。
3 统一认证UAA集成
3.1 初始化数据库
执行资料下/数据库脚本/xc_uaa.sql 和 xc_user.sql
3.2 工程导入
1复制xc-uaa-gateway-server、xc-uaa、xc-user到xc-parent父工程
2添加上述三个Module
3完成后,整体目录结构如下:
3.3 配置中心
3.3.1 网关服务
在 nacos 中创建 uaa-gateway-server-dev.properties ,并添加下面的配置
#srpingboot http 配置信息
server.servlet.context-path = /
server.port=63010
在 xc-gateway-server 服务中引入nacos配置信息,需要引入对 ribbon 和 feign 公共配置信息。
#微服务启动参数
spring:
application:
name: uaa-gateway-server
main:
allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定
cloud:
nacos:
discovery: #配置注册中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
config: #配置中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
file-extension: properties
shared-configs:
- dataId: spring-http-config.properties
group: ${group.name}
- dataId: feign-config.properties
group: ${group.name}
- dataId: ribbon-config.properties
group: ${group.name}
profiles: # 激活配置环境
active: dev
# 组名称
group:
name: xc-group
3.3.2 UAA服务
在 nacos 中创建 uaa-service-dev.properties ,并添加下面的配置
#srpingboot http 配置信息
server.servlet.context-path = /uaa
server.port=63020
spring.datasource.url = jdbc:mysql://192.168.94.129:3306/xc_uaa?userUnicode=true&useSSL=false&characterEncoding=utf8
在 xc-uaa 服务中引入nacos配置信息,需要引入对 ribbon 、freemarker 和 feign 公共配置信息。
#微服务启动参数
spring:
application:
name: uaa-service
main:
allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定
cloud:
sentinel:
transport:
dashboard: 192.168.94.129:8858 #sentinel控制台地址
nacos:
discovery: #配置注册中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
config: #配置中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
file-extension: properties
shared-configs:
- dataId: spring-http-config.properties
group: ${group.name}
- dataId: spring-druid-config.properties
group: ${group.name}
- dataId: feign-config.properties
group: ${group.name}
- dataId: ribbon-config.properties
group: ${group.name}
- dataId: freemarker-config.properties
group: ${group.name}
profiles: # 激活配置环境
active: dev
# 组名称
group:
name: xc-group
3.3.3 统一账号服务
在 nacos 中创建 user-service-dev.properties ,并添加下面的配置
#srpingboot http 配置信息
server.servlet.context-path = /user
server.port=63130
spring.datasource.url = jdbc:mysql://192.168.94.129:3306/xc_user?userUnicode=true&useSSL=false&characterEncoding=utf8
在 xc-uaa 服务中引入nacos配置信息,需要引入对 ribbon 、mp 和 feign 公共配置信息
#微服务启动参数
spring:
application:
name: user-service
main:
allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定
cloud:
sentinel:
transport:
dashboard: 192.168.94.129:8858 #sentinel控制台地址
nacos:
discovery: #配置注册中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
config: #配置中心
server-addr: 192.168.94.129:8848
namespace: 5c0b093c-4084-46b5-bf33-899321cb7ef5
group: ${group.name}
file-extension: properties
shared-configs:
- dataId: mp-config.properites
group: ${group.name}
- dataId: spring-http-config.properties
group: ${group.name}
- dataId: spring-druid-config.properties
group: ${group.name}
- dataId: feign-config.properties
group: ${group.name}
- dataId: ribbon-config.properties
group: ${group.name}
profiles: # 激活配置环境
active: dev
# 组名称
group:
name: xc-group
4.Oauth2授权模式
Oauth2.0 是一个第三方的认证协议。
在 Oauth2.0 认证协议中,主要包含下面的集中模式:
●授权码模式(Authorization Code) 适用于:第三方Web服务器端应用与第三方原生App。
●隐式授权模式(Implicit) 适用于:第三方单页面应用。
●密码模式(Resource Owner Password Credentials) 适用于:第一方单页应用与第一方原生App。
●客户端模式(Client Credentials) 没有用户参与的,完全信任的一方或合作方服务器端服务
其中授权码模式和密码模式应用较多,课程中将采用密码模式来完成用户的校验,下面将使用 UAA 系统来演示 Oauth2 密码模式授权,对于Oauth2 其他内容,请参考专题课程:Spring Security Oauth2 。
4.1 Oauth2密码模式授权
下面功能演示会使用 Post man 来访问 UAA 工程完成 Oauth2 密码模式的认证测试。
4.1.1 认证测试
功能说明: 用户登录并返回令牌,该令牌用于访问学成在线平台内受保护资源。
访问路径:POST http://127.0.0.1:63010/uaa/oauth/token (由 Spring Security Oauth2 框架提供)
启动服务:
●Nacos(注册中心)
●xc-uaa-gateway-sever(UAA网关中心)
●xc-user-service(用户中心)
●xc-uaa(认证中心)
请求参数:
●grant_type: 授权类型,可以是authorization_code,implicit,client_credentials,password
●client_id:接入客户端id(在xc-uaa数据库中的oauth_client_details表中)
●client_secret:接入客户端密钥(在xc-uaa数据库中的oauth_client_details表中)
●username:登录用户名,认证类型(如密码认证,手机号认证,短信认证,二维码认证等,在xc-user数据库中的account表中)
{"username":"15022222227","authenticationType":"mobile"} //用户通过手机进行认证
或
{"username":"15022222227","authenticationType":"mobile"} //用户通过手机进行认证
说明:实现手机和密码登录,参照TenantServiceImpl 的authentication 方法
注意:
username字段:username为关联键,同一个用户在两表中该字段需保持一致。
mobile字段:mobile 为关联键,同一个用户在两表中该字段需保持一致。
salt 字段:salt 为加密盐,一共为 5 位数字,其内容由 数字/大小写字母 组成。
●password:登录密码(在xc-user数据库中的account表中)
注意:
password 字段:算法为Md5(明文password + salt)
如:1234567(明文密码) + 2FygE(盐) = 12345672FygE
最终的密文密码为:md5(12345672FygE) = ef520aa1611491120e5363d7089ea918
请求示例
响应内容:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", //令牌
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", //刷新令牌
"expires_in": 31535999, //有效期
"scope": "read",
"jti": "dfc6f30a-aa8e-4028-a43a-1487e64a2cfb"
}
4.1.2 解析令牌
功能说明:返回令牌的明文内容,描述的是当前登录的用户及接入客户端的信息。
访问路径:Post http://127.0.0.1:63010/uaa/oauth/check_token (UAA服务需要开发人员自行实现)
请求参数:
●token: “eyJhbGciOiJIfdasfdajgfsiogjfisnijiIFDJGDfhdsog…”
请求示例
响应内容:
{
"aud": [
"xuecheng-resource"
],
"payload": {
"1177144209463128125": {
"resources": null,
"user_authorities": {
"r_xc_com": [
"xc_course_base_list",
//省略其他
]
}
}
},
"user_name": "xc-user-first",
"scope": [
"read"
],
"mobile": "15022222227",
"exp": 1658931060,
"client_authorities": [
"ROLE_XC_API"
],
"jti": "3fe0260c-a3f6-434b-95eb-87b141b8c013",
"client_id": "xc-com-platform"
}
4.1.3 刷新令牌
功能说明: 用户获得的令牌是有有效期的,当令牌失效后,需要对令牌进行刷新操作
访问路径:POST http://127.0.0.1:63010/uaa/oauth/token (由 Spring Security Oauth2 框架提供)
启动服务:
●Nacos(注册中心)
●xc-uaa-gateway-sever(UAA网关中心)
●xc-user-service(用户中心)
●xc-uaa(认证中心)
请求参数:
●grant_type: 固定值为 refresh_token
●refresh_token:刷新令牌的具体值(在获得令牌的时候拿到)
请求示例
4.1.4 总结
提供认证的服务方:xc-uaa 服务
认证使用的框架:Spring Security Oauth2
访问地址:
1.申请令牌
http://127.0.0.1:63010/uaa/oauth/token
框架提供
2.检查令牌
http://127.0.0.1:63010/uaa/oauth/check_token
xc-uaa服务的controller提供
3.刷新令牌
http://127.0.0.1:63010/uaa/oauth/token
框架提供
特点:
1.一般有前端在访问令牌失效的情况下,会调用此接口
2.刷新令牌的存活时间会比访问令牌时间长
UAA数据的特点:
1.xc-uaa服务
数据库存放的是客户端的数据(商户数据)
2.xc-user服务
数据库存用户的数据
4.2 JWT 的简介
在 4.1.1 中认证测试完后返回的内容中,包含下面的内容,如下:
●相应内容
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", //令牌
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", //刷新令牌
"expires_in": 31535999, //有效期
"scope": "read",
"jti": "dfc6f30a-aa8e-4028-a43a-1487e64a2cfb"
}
内容中的第一个属性 access_token 后面的值为用户访问令牌,Oauth2 中的访问令牌其实使用的是 JWT 令牌。下面将讲解 JWT令牌的相关内容。
4.2.1 JWT令牌的介绍
什么是JWT?
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。
JWT令牌的优点:
1、jwt基于json,非常方便解析。
2、可以在令牌中自定义丰富的内容,易扩展。
3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
4.2.2 JWT令牌结构
JWT令牌结构:
JWT令牌由Header、Payload、Signature三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
●Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)。
一个例子:
{
"alg": "HS256",
"typ": "JWT"
}
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
●Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比
如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
一个例子:
{
"sub": "1234567890",
"name": "456",
"admin": true
}
最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。
●Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明
签名算法进行签名。
一个例子:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。
4.2.3 JWT令牌解析
在用户登录成功后,可以获得认证后的信息,如下:
获得令牌信息
其中 access_token 后的值为 JWT 令牌, JWT 令牌分为三部分,前两部分都是通过 Header 和 Payload 都是可以通过 Base64 进行解析,下面将来演示 JWT 令牌的解析,我们将以下面的令牌为例子,如下:
令牌示例
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsieHVlY2hlbmctcmVzb3VyY2UiXSwicGF5bG9hZCI6eyIxMjA2ODU3NDExMTMzMTgxOTU5Ijp7InJlc291cmNlcyI6bnVsbCwidXNlcl9hdXRob3JpdGllcyI6eyJyX3hjX2NvbV9hZG1pbiI6WyJ4Y19jb3Vyc2VfYmFzZV9saXN0IiwieGNfY291cnNlX2Jhc2Vfc2F2ZSIsInhjX2NvdXJzZV9iYXNlX2VkaXQiLCJ4Y19jb3Vyc2VfYmFzZV9kZWwiLCJ4Y19jb3Vyc2VfYmFzZV92aWV3IiwieGNfdGVhY2hwbGFuX3ZpZXciLCJ4Y190ZWFjaHBsYW5fc2F2ZV9tb2RpZnkiLCJ4Y190ZWFjaHBsYW5fZGVsIiwieGNfbWFya2V0X3NhdmVfbW9kaWZ5IiwieGNfbWFya2V0X3ZpZXciLCJ4Y19jb3Vyc2VfcHVibGlzaCIsInhjX21lZGlhX2xpc3QiLCJ4Y19tZWRpYV9zYXZlIiwieGNfbWVkaWFfcHJldmlldyIsInhjX21lZGlhX2RlbCIsInhjX2NvbXBhbnlfbW9kaWZ5IiwieGNfY29tcGFueV92aWV3IiwieGNfdGVhY2hlcl9saXN0IiwieGNfdGVhY2hlcl9zYXZlIiwieGNfdGVhY2hlcl9tb2RpZnkiLCJ4Y190ZWFjaHBsYW53b3JrX2xpc3QiLCJ4Y190ZWFjaHBsYW53b3JrX3NhdmVfbW9kaWZ5IiwieGNfdGVhY2hwbGFud29ya19kZWwiXX19fSwidXNlcl9uYW1lIjoid1Z1MTg2MTExMDY5ODQiLCJzY29wZSI6WyJyZWFkIl0sIm1vYmlsZSI6IjE4NjExMTA2OTg0IiwiZXhwIjoxNjUzNTk4ODU0LCJjbGllbnRfYXV0aG9yaXRpZXMiOlsiUk9MRV9YQ19BUEkiXSwianRpIjoiNmEzMjg4ZGUtNzYyNS00MjMxLTkyYWYtZTFiZmE0NjdmOGVjIiwiY2xpZW50X2lkIjoieGMtY29tLXBsYXRmb3JtIn0.nC5D3fRQXEkW54ly4Om5pnVu93vwkXl8mfIc54KFzUw",
........
}
4.2.3.1 解析 Header 部分
下面我将演示 JWT 令牌 Header 部分的解析
●解析内容(Header)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
代码解析方法
public class JwtTest {
@Test
public void header() {
byte[] decode = Base64.getDecoder().decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
System.out.println(new String(decode));
}
}
网站工具解析方法 我们将通过网络上的工具解析有 Base64 加密过的内容,网站为:https://www.sojson.com/base64.html解析示例图:
4.2.3.2 解析 Payload 部分
下面我将演示 JWT 令牌 Payload 部分的解析
●解析内容(Payload )
eyJhdWQiOlsieHVlY2hlbmctcmVzb3VyY2UiXSwicGF5bG9hZCI6eyIxMjA2ODU3NDExMTMzMTgxOTU5Ijp7InJlc291cmNlcyI6bnVsbCwidXNlcl9hdXRob3JpdGllcyI6eyJyX3hjX2NvbV9hZG1pbiI6WyJ4Y19jb3Vyc2VfYmFzZV9saXN0IiwieGNfY291cnNlX2Jhc2Vfc2F2ZSIsInhjX2NvdXJzZV9iYXNlX2VkaXQiLCJ4Y19jb3Vyc2VfYmFzZV9kZWwiLCJ4Y19jb3Vyc2VfYmFzZV92aWV3IiwieGNfdGVhY2hwbGFuX3ZpZXciLCJ4Y190ZWFjaHBsYW5fc2F2ZV9tb2RpZnkiLCJ4Y190ZWFjaHBsYW5fZGVsIiwieGNfbWFya2V0X3NhdmVfbW9kaWZ5IiwieGNfbWFya2V0X3ZpZXciLCJ4Y19jb3Vyc2VfcHVibGlzaCIsInhjX21lZGlhX2xpc3QiLCJ4Y19tZWRpYV9zYXZlIiwieGNfbWVkaWFfcHJldmlldyIsInhjX21lZGlhX2RlbCIsInhjX2NvbXBhbnlfbW9kaWZ5IiwieGNfY29tcGFueV92aWV3IiwieGNfdGVhY2hlcl9saXN0IiwieGNfdGVhY2hlcl9zYXZlIiwieGNfdGVhY2hlcl9tb2RpZnkiLCJ4Y190ZWFjaHBsYW53b3JrX2xpc3QiLCJ4Y190ZWFjaHBsYW53b3JrX3NhdmVfbW9kaWZ5IiwieGNfdGVhY2hwbGFud29ya19kZWwiXX19fSwidXNlcl9uYW1lIjoid1Z1MTg2MTExMDY5ODQiLCJzY29wZSI6WyJyZWFkIl0sIm1vYmlsZSI6IjE4NjExMTA2OTg0IiwiZXhwIjoxNjUzNTk4ODU0LCJjbGllbnRfYXV0aG9yaXRpZXMiOlsiUk9MRV9YQ19BUEkiXSwianRpIjoiNmEzMjg4ZGUtNzYyNS00MjMxLTkyYWYtZTFiZmE0NjdmOGVjIiwiY2xpZW50X2lkIjoieGMtY29tLXBsYXRmb3JtIn0
●代码解析方法
public class JwtTest {
@Test
public void header() {
byte[] decode = Base64.getDecoder().decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
System.out.println(new String(decode));
}
}
网站工具解析方法 我们将通过网络上的工具解析有 Base64 加密过的内容,网站为:https://www.sojson.com/base64.html解析示例图:
将解析后的内容格式化如下:
{
"aud": [
"xuecheng-resource"
],
"payload": {
"1206857411133181959": {
"resources": null,
"user_authorities": {
"r_xc_com_admin": [
......
]
}
}
},
"user_name": "wVu18611106984",
"scope": [
"read"
],
"mobile": "18611106984",
"exp": 1653598854,
"client_authorities": [
"ROLE_XC_API"
],
"jti": "6a3288de-7625-4231-92af-e1bfa467f8ec",
"client_id": "xc-com-platform"
}
4.2.3.3 解析 Signature 部分
下面我将演示 JWT 令牌 Signature 部分的解析
●解析内容(Signature )
nC5D3fRQXEkW54ly4Om5pnVu93vwkXl8mfIc54KFzUw
●代码解析方法
public class JwtTest {
@Test
public void header() {
byte[] decode = Base64.getDecoder().decode("nC5D3fRQXEkW54ly4Om5pnVu93vwkXl8mfIc54KFzUw");
System.out.println(new String(decode));
}
}
运行报错,无法解析。
●解析方法 我们将通过网络上的工具解析有 Base64 加密过的内容,网站为:https://www.sojson.com/base64.html解析示例图:
在上面的解析结果内容上可以看到,第三部部分 Signature 经过加密后,解析的内容是不可读的,无法识别。
5.相关解释
5.1 JWT 的加密方式
加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),其逆过程就是解码(解密),加密技术的要点是加密算法,加密算法可以分为三类:
1.对称加密,如AES
基本原理:将明文分成N个组,然后使用密钥对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。
优势:算法公开、计算量小、加密速度快、加密效率高
缺陷:双方都使用同样密钥,安全性得不到保证
2.非对称加密,如RSA
基本原理:同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端
私钥加密,持有私钥或公钥才可以解密
公钥加密,持有私钥才可解密
优点:安全,难以破解
缺点:算法比较耗时
3.不可逆加密,如MD5,SHA
基本原理:加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,无法根据密文推算出明文。
5.2 JWT 的编码
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。
在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。
Base64索引表:
●编码“Man”
●编码文章
举例来说,一段引用自托马斯·霍布斯《利维坦)》的文句:
Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.
编译后:
TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=