6.3.1 JWT介绍
通过上边的测试我们发现,当资源服务和授权服务不在一起时资源服务使用RemoteTokenServices 远程请求授权服务验证token,如果访问量较大将会影响系统的性能 。
解决上边问题:
令牌采用JWT格式即可解决上边的问题,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。
1、什么是JWT?
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。
官网:JWT.IO
标准: JSON Web Token JWT)
JWT令牌的优点:
1)jwt基于json,非常方便解析。
2)可以在令牌中自定义丰富的内容,易扩展。
3)通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
4)资源服务使用JWT可不依赖认证服务即可完成授权。
缺点:
1)JWT令牌较长,占存储空间比较大。
2、JWT令牌结构
通过学习JWT令牌结构为自定义jwt令牌打好基础。
JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
- Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)
一个例子如下:
下边是Header部分的内容
{ "alg": "HS256","typ": "JWT"
}
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
- Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。
一个例子:
{ "sub": "1234567890","name": "456","admin": true
}
- Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明签名算法进行签名。
一个例子:
HMACSHA256 base64UrlEncodeheader) + "." +base64UrlEncodepayload),secret)
base64UrlEncodeheader):jwt令牌的第一部分。
base64UrlEncodepayload):jwt令牌的第二部分。
secret:签名所使用的密钥。
6.3.2 配置JWT令牌服务
在uaa中配置jwt令牌服务,即可实现生成jwt格式的令牌。
1、TokenConfig
@Configuration
2、定义JWT令牌服务
@Autowired
6.3.3 生成jwt令牌
6.3.4 校验jwt令牌
资源服务需要和授权服务拥有一致的签字、令牌服务等:
1、将授权服务中的TokenConfig类拷贝到资源 服务中
2、屏蔽资源 服务原来的令牌服务类
@Configuration
3、测试
1)申请jwt令牌
2)使用令牌请求资源
小技巧:
令牌申请成功可以使用/uaa/oauth/check_token校验令牌的有效性,并查询令牌的内容,例子如下:
6.4 完善环境配置
截止目前客户端信息和授权码仍然存储在内存中,生产环境中通过会存储在数据库中,下边完善环境的配置:
6.4.1 创建表
在user_db中创建如下表:
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` `client_id` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端标
识',`resource_ids` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '接入资源列表',`client_secret` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '客户端秘钥',`scope` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`authorized_grant_types` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT
NULL,`web_server_redirect_uri` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT
NULL,`authorities` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`access_token_validity` int11) NULL DEFAULT NULL,`refresh_token_validity` int11) NULL DEFAULT NULL,`additional_information` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,`create_time` timestamp0) NOT NULL DEFAULT CURRENT_TIMESTAMP0) ON UPDATE
CURRENT_TIMESTAMP0),`archived` tinyint4) NULL DEFAULT NULL,`trusted` tinyint4) NULL DEFAULT NULL,`autoapprove` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY `client_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '接入客户端信息'
ROW_FORMAT = Dynamic;
INSERT INTO `oauth_client_details` VALUES 'c1', 'res1',
'$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm', 'ROLE_ADMIN,ROLE_USER,ROLE_API',
'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com',
NULL, 7200, 259200, NULL, '2019‐09‐09 16:04:28', 0, 0, 'false');
INSERT INTO `oauth_client_details` VALUES 'c2', 'res2',
'$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm', 'ROLE_API',
'client_credentials,password,authorization_code,implicit,refresh_token', 'http://www.baidu.com',
NULL, 31536000, 2592000, NULL, '2019‐09‐09 21:48:51', 0, 0, 'false');
oauth_code表,Spring Security OAuth2使用,用来存储授权码:
DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code` `create_time` timestamp0) NOT NULL DEFAULT CURRENT_TIMESTAMP,`code` varchar255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`authentication` blob NULL,INDEX `code_index``code`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
6.4.2 配置授权服务
(1)修改AuthorizationServer:
ClientDetailsService和AuthorizationCodeServices从数据库读取数据。
@Configuration
6.4.3测试
1、测试申请令牌
使用密码模式申请令牌,客户端信息需要和数据库中的信息一致。
POST http://localhost:53020/uaa/oauth/token
2、测试授权码模式
生成的授权存储到数据库中。
http://localhost:53020/uaa/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
注意scope=?,查看数据库
POST http://localhost:53020/uaa/oauth/token