JWT令牌生成与校验

article/2025/10/16 18:23:34

目录

  • 1 JWT介绍
    • 1.1 什么是JWT?
    • 1.2 JWT令牌结构
  • 2 配置JWT令牌服务
  • 3 生成JWT令牌
  • 4 校验JWT令牌
  • 5 JWT整合Spring Security
    • 5.1 创建表
  • 6 配置授权服务
    • 6.1 测试


1 JWT介绍

通过上边的测试我们发现,当资源服务和授权服务不在一起时资源服务使用RemoteTokenServices 远程请求授权服务验证token,如果访问量较大将会影响系统的性能 。

解决上边问题:

令牌采用JWT格式即可解决上边的问题,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。

1.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令牌较长,占存储空间比较大。

1.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( base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)

base64UrlEncode(header):jwt令牌的第一部分。

base64UrlEncode(payload):jwt令牌的第二部分。

secret:签名所使用的密钥。

2 配置JWT令牌服务

在uaa中配置jwt令牌服务,即可实现生成jwt格式的令牌。

1、TokenConfig

@Configuration 
public class TokenConfig {private String SIGNING_KEY = "uaa123";@Beanpublic TokenStore tokenStore() {return new JwtTokenStore(accessTokenConverter());}@Beanpublic JwtAccessTokenConverter accessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey(SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证return converter;}
}

2、定义JWT令牌服务

@Autowired
private JwtAccessTokenConverter accessTokenConverter;@Beanpublic AuthorizationServerTokenServices tokenService() {DefaultTokenServices service=new DefaultTokenServices();service.setClientDetailsService(clientDetailsService);service.setSupportRefreshToken(true);service.setTokenStore(tokenStore);
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天return service;}

3 生成JWT令牌

在这里插入图片描述
响应:
在这里插入图片描述

4 校验JWT令牌

资源服务需要和授权服务拥有一致的签字、令牌服务等:

1、将授权服务中的TokenConfig类拷贝到资源 服务中

2、屏蔽资源 服务原来的令牌服务类

@Configuration 
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResouceServerConfig extendsResourceServerConfigurerAdapter {public static final String RESOURCE_ID = "res1";@AutowiredTokenStore tokenStore;//资源服务令牌解析服务
//    @Bean
//    public ResourceServerTokenServices tokenService() {
//        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
//        RemoteTokenServices service=new RemoteTokenServices(); 
//        service.setCheckTokenEndpointUrl("http://localhost:53020/uaa/oauth/check_token");
//        service.setClientId("c1");
//        service.setClientSecret("secret");
//        return service;
//    }@Overridepublic void configure(ResourceServerSecurityConfigurer resources) {resources.resourceId(RESOURCE_ID).tokenStore(tokenStore).stateless(true);}

3、测试

1)申请jwt令牌

2)使用令牌请求资源

在这里插入图片描述

小技巧:

令牌申请成功可以使用/uaa/oauth/check_token校验令牌的有效性,并查询令牌的内容,例子如下:

在这里插入图片描述

5 JWT整合Spring Security

截止目前客户端信息和授权码仍然存储在内存中,生产环境中通过会存储在数据库中,下边完善环境的配置:

5.1 创建表

在user_db中创建如下表:

DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details`  (`client_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户端标
识',`resource_ids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '接入资源列表',`client_secret` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
COMMENT '客户端秘钥',`scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`authorized_grant_types` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT
NULL,`web_server_redirect_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT
NULL,`authorities` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`access_token_validity` int(11) NULL DEFAULT NULL,`refresh_token_validity` int(11) NULL DEFAULT NULL,`additional_information` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,`create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE
CURRENT_TIMESTAMP(0),`archived` tinyint(4) NULL DEFAULT NULL,`trusted` tinyint(4) NULL DEFAULT NULL,`autoapprove` varchar(255) 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` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,`code` varchar(255) 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 配置授权服务

(1)修改AuthorizationServer:

ClientDetailsService和AuthorizationCodeServices从数据库读取数据。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends
AuthorizationServerConfigurerAdapter {        
@Autowired    
private TokenStore tokenStore;    
@Autowired    
private JwtAccessTokenConverter accessTokenConverter;    
@Autowired    
private ClientDetailsService clientDetailsService;    
@Autowired    
private AuthorizationCodeServices authorizationCodeServices;    
@Autowired    
private AuthenticationManager authenticationManager;    
/**    * 1.客户端详情相关配置    */    
@Bean    public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean    
public ClientDetailsService clientDetailsService(DataSource dataSource) {    
ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);        
((JdbcClientDetailsService)
clientDetailsService).setPasswordEncoder(passwordEncoder());return clientDetailsService;        
}    
@Override 
public void configure(ClientDetailsServiceConfigurer clients)    
throws Exception {            
clients.withClientDetails(clientDetailsService);        
}    
/**    * 2.配置令牌服务(token services)    */    
@Bean    
public AuthorizationServerTokenServices tokenService() {    
DefaultTokenServices service=new DefaultTokenServices();        
service.setClientDetailsService(clientDetailsService);        
service.setSupportRefreshToken(true);//支持刷新令牌        
service.setTokenStore(tokenStore); //绑定tokenStore        
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();        
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));        
service.setTokenEnhancer(tokenEnhancerChain);        
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时        
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3return service;        
}    
/**    * 3.配置令牌(token)的访问端点    */    
@Bean    
public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {     
return new JdbcAuthorizationCodeServices(dataSource);//设置授权码模式的授权码如何存取        
}    
@Override    
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {    
endpoints.authenticationManager(authenticationManager)        
.authorizationCodeServices(authorizationCodeServices)                
.tokenServices(tokenService())                
.allowedTokenEndpointRequestMethods(HttpMethod.POST);                
}    
/**    * 4.配置令牌端点(Token Endpoint)的安全约束    */    
@Override    
public void configure(AuthorizationServerSecurityConfigurer security){    
security        
.tokenKeyAccess("permitAll()")                
.checkTokenAccess("permitAll()")                
.allowFormAuthenticationForClients()//允许表单认证                
;
}    
}

6.1 测试

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

http://chatgpt.dhexx.cn/article/fedALhu2.shtml

相关文章

信息系统基础知识(笔记)

一、信息 1.1、信息的基本概念 信息就是信息,既不是物质们也不是论量,信息是能够用来消除不确定的东西 两个概念层次:本体论(客观层,与课客体本身因素相关,与主题因素无关) 认知论&#xff0…

计算机毕业论文内容参考|基于大数据的信息物理融合系统的分析与设计方法

文章目录 导文摘要前言绪论课题背景国内外现状与趋势:课题内容:相关技术与方法介绍:系统架构设计:数据采集与处理:数据存储与管理:数据分析与挖掘:系统优化与调试:应用场景:挑战与机遇:研究方向:系统分析:系统设计:系统实现:系统测试:总结与展望:

工业4.0中的人-信息-物理系统集成(HSI):设计与评估方法

于栖洋 译 摘要:本文概述了工业4.0中集成人和信息物理系统的设计和使用空间,特别关注分析、设计和评估方法和阶段的相互作用。本文首先介绍了工业4.0面临的挑战,综述了现有的系统设计方法,描述了方法模型的设计和使用空间,并以工…

信息系统基本知识(六)

大纲 信息系统与信息化信息系统开发方法常规信息系统集成技术软件工程新一代信息技术信息系统安全技术信息化发展与应用信息系统服务管理信息系统服务规划企业首席信息管及其责任 1.7 信息化发展与应用 我国在“十三五”规划纲要中,将培育人工智能、移动智能终端…

Unity物理系统(一)物理系统相关组件

一、物理系统相关组件 Unity中的物理系统涉及的组件分为如下几类: 刚体角色控制器碰撞体布料关节力场 二、刚体(Rigidbody) Rigidbody(刚体)组件可以使游戏对象在物理系统的控制下进行运动,Rigidbody …

工业信息物理系统测试验证平台(ETest_CPS)

1.产品简介 ETest_CPS是基于ETest Studio开发出的工业信息物理系统测试验证平台(Embedded System Test Studiofor Cyber-Physical System,简称:ETest_CPS)。ETest_CPS由软件和硬件组成,软件采用ETest,硬件包括测试机柜…

信息化与信息系统5

信息系统规划 大型信息系统的特点 考点: 具体包括以下6点: 规模庞大,跨地域性,网络结构复杂,业务种类多,数量大,用户多。 信息系统规划方法 规划流程 1. 分析企业信息化的现状 2. 制定企…

信息物理社会融合系统:一种以数据为中心的框架

信息物理社会融合系统:一种以数据为中心的框架 翟书颖1, 郭斌2, 李茹1, 王庭良1, 於志文2, 周兴社2 1. 西北工业大学明德学院,陕西 西安 710129 2. 西北工业大学计算机学院,陕西 西安 710129 摘要:信息物理社会融合系统连接信息空…

ETest_CPS——工业信息物理系统测试验证平台

1)产品简介 ETest_CPS是一款工业信息物理系统测试验证平台(Embedded System Test Studio for Cyber-Physical System,简称:ETest_CPS)。ETest_CPS由软件和硬件组成,软件采用ETest,硬件包括测试机柜、测试主…

信息物理系统-Rijndael加密算法的实现

信息物理系统-Rijndael加密算法的实现: 概述: AES标准的Rijndael算法是一种分组加密算法,本次实验通过PtolemyII软件,实现了明文长度为128位,密钥长度为128位的Rijndael加密算法。 实验的完成采取自底向上的&#x…

信息化与信息系统4

信息安全概念 安全分层 信息安全分为4层:设备安全,数据安全,内容安全,行为安全 会给出某些特性,要求反向选择是属于哪一层。 信息系统的安全保护等级 第一级:对个人,公司造成损害 第二级&a…

物理系统(一)

物理系统主要由以下几部分组成:Rigidbody(刚体)、Character Controller(角色控制器)、Collider(碰撞器)、Cloth(布料)、Joint(关节) 如图&#xf…

计算机信息系统

一、概念 (1) 计算机信息系统( Computer_based Information System ,简称信息系统)是一类以提供信息服务 为主要目的的数据密集型、人机交互的计算机应用系统。 (2)由计算机及其相关的和配套的…

物理服务器的信息,信息物理系统

信息物理系统(CPS,Cyber-Physical Systems)是一个综合计算、网络和物理环境的多维复杂系统,通过3C(Computation、Communication、Control)技术的有机融合与深度协作,实现大型工程系统的实时感知、动态控制和信息服务。CPS实现计算、通信与物理系统的一体…

小白聊智慧制造:一文读懂信息物理系统(CPS)

随着我国“中国制造2025”的不断深入,越来越多的制造业企业在探索中国的制造业升级。制造业的智能升级有美国的工业互联网和德国的工业4.0两种方式,根据我国制造业所处的阶段,大多数企业选择德国工业4.0的方案。工业4.0的方案之中&#xff0c…

软考 - 05 信息物理系统(Cyber Physical Systems, CPS)

文章目录 题目【问题1】【答案1】【问题2】【答案2】【问题3】【答案3】 题目 信息物理系统(Cyber Physical Systems, CPS)技术己成为未来宇航装备发展的重点关键技术之一。某公司长期从事嵌入式系统的研制工作,随着公司业务范围不断扩展,公…

LFU 的设计与实现

LFU 的设计与实现 作者:Grey 原文地址: 博客园:LFU 的设计与实现 CSDN:LFU 的设计与实现 题目描述 LFU(least frequently used)。即最不经常使用页置换算法。 题目链接:LeetCode 460. LF…

Redis的LRU和LFU浅谈

1.概论 Redis中的缓存淘汰算法大体分为两种,volatile-xxx和allkeys-xxx。volatile-xxx 是对带过期时间的 key 进行淘汰,即使用了expire的key;allkeys-xxx 策略会对所有的key 进行淘汰。如果只是用redis做缓存,几乎不使用持久…

LFU五种实现方式,从简单到复杂

前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊。这个月我估计都是中等和困难题,没有简单题了。 幸好,力扣上有各种大牛给写题解。看着他们行云流水的代码,真的是羡慕不已。让我印象最深刻的就是人称 “甜…

LRU和LFU

LRU 根据题意&#xff0c;使用过的数据放在链表的尾部&#xff0c;容量满了就删除链表的头&#xff0c;使用的数据结构是LinkedHashMap。 146. LRU 缓存(中等) class LRUCache {private int cap;private LinkedHashMap<Integer, Integer> list;public LRUCache(int…