目录
- 前言
- 1. 基本知识
- 2. Demo
- 3. 实战
前言
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
- 【Java项目】实战CRUD的功能整理(持续更新)
1. 基本知识
JwtAccessTokenConverter 是 Spring Security OAuth2 中的一个重要组件,主要用于生成和验证 JSON Web Token (JWT)
-  JWT 的结构: 
 JWT 由三部分组成:头部(Header)、负载(Payload)和签名(Signature)
 头部通常包含令牌的类型(JWT)和签名算法(如 HMAC SHA256)
 负载部分包含声明(Claims),即与用户相关的信息,例如权限、过期时间等
 签名是使用头部和负载生成的,用于验证令牌的完整性
-  类继承关系: 
 JwtAccessTokenConverter 继承自 AbstractTokenConverter,并实现了 AccessTokenConverter 接口
 该类负责将 OAuth2 访问令牌与 JWT 进行转换和处理
-  主要方法: 
 encode:用于生成 JWT,接受 OAuth2AccessToken 和 OAuth2Authentication 参数
 decode:用于解析和验证 JWT,返回 OAuth2AccessToken 实例
常用的几个类如下:
-  Access Token:
 OAuth2 中的访问令牌,用于授权客户端访问受保护资源
 JWT 是一种常用的访问令牌格式
-  OAuth2Authentication:
 封装与用户相关的身份验证信息,包括用户的身份和权限
-  Additional Information:
 JWT 中可以包含附加信息,通常用于存储用户 ID、用户名、权限等自定义字段
2. Demo
-  签名密钥:在 main 方法中使用 demo.setSigningKey(signingKey); 设置签名密钥,以确保生成的 JWT 是安全的 
-  用户权限和身份验证:使用 SimpleGrantedAuthority 创建用户的角色,并通过 TestingAuthenticationToken 实现身份验证 
-  OAuth2AccessToken:创建访问令牌,附加用户 ID、用户名和权限信息 
-  JWT 生成与解码:调用 encode 方法生成 JWT,然后使用 Base64 解码打印出 JWT 的头部和负载部分 
常用的xml配置文件如下:
<!-- https://mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2 -->
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.5.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
    <version>1.1.0.RELEASE</version> <!-- 确保版本与 Spring Security 兼容 -->
</dependency>
执行代码如下:
package JwtDemo;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import java.util.*;
public class JwtDemo extends JwtAccessTokenConverter {
    public static void main(String[] args) {
        JwtDemo demo = new JwtDemo();
        String signingKey = "your-signing-key"; // 请替换为你的签名密钥
        demo.setSigningKey(signingKey);
        // 创建用户权限
        Set<SimpleGrantedAuthority> authorities = new HashSet<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        // 创建 OAuth2Request
        OAuth2Request request = new OAuth2Request(null, "client_id",
                authorities, true, null, null, null, null, null);
        // 创建 Authentication
        Authentication authentication = new TestingAuthenticationToken("user", "password", authorities);
        // 创建 OAuth2Authentication
        OAuth2Authentication oauth2Authentication = new OAuth2Authentication(request, authentication);
        // 创建 OAuth2AccessToken 实例
        DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken("your-jwt-token");
        Map<String, Object> additionalInformation = new HashMap<>();
        additionalInformation.put("user_id", "12345"); // 添加用户信息
        additionalInformation.put("user_name", "user"); // 添加用户名
        additionalInformation.put("authorities", authorities); // 添加权限
        token.setAdditionalInformation(additionalInformation);
        // 使用 JwtDemo 生成 JWT
        String jwt = demo.encode(token, oauth2Authentication);
        System.out.println("生成的 JWT: " + jwt);
        String[] chunks = jwt.split("\\.");
        Base64.Decoder decoder = Base64.getUrlDecoder();
        try {
            String header = new String(decoder.decode(chunks[0]));
            String payload = new String(decoder.decode(chunks[1]));
            System.out.println("Header: " + header);
            System.out.println("Payload: " + payload);
        } catch (IllegalArgumentException e) {
            System.err.println("解码时出错: " + e.getMessage());
        }
    }
}
// 自定义的 Authentication 实现
class TestingAuthenticationToken extends org.springframework.security.authentication.UsernamePasswordAuthenticationToken {
    public TestingAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(principal, credentials, authorities);
    }
}
截图如下:

3. 实战
已Bledex源码实战为例
@Configuration  // 标记为配置类,Spring会自动扫描并加载
@ConditionalOnProperty(prefix = "blade.security.oauth2", name = "storeType", havingValue = "jwt", matchIfMissing = true) 
// 当配置中 "blade.security.oauth2.storeType" 为 "jwt" 时,才加载此配置类
public class JwtTokenStoreConfiguration {
	/**
	 * 使用 jwtTokenStore 存储 token
	 */
	@Bean  // 将方法的返回值注册为 Spring 的 Bean
	public TokenStore jwtTokenStore(JwtProperties jwtProperties) {
		// 创建 JwtTokenStore 实例,并传入 JwtAccessTokenConverter
		return new JwtTokenStore(jwtAccessTokenConverter(jwtProperties));
	}
	/**
	 * 用于生成 jwt
	 */
	@Bean  // 将方法的返回值注册为 Spring 的 Bean
	public JwtAccessTokenConverter jwtAccessTokenConverter(JwtProperties jwtProperties) {
		JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
		// 设置 JWT 签名密钥
		accessTokenConverter.setSigningKey(jwtProperties.getSignKey());
		return accessTokenConverter;  // 返回配置好的 JwtAccessTokenConverter
	}
	/**
	 * 用于扩展 jwt
	 */
	@Bean
	@ConditionalOnMissingBean(name = "jwtTokenEnhancer") 
	// 当 Spring 容器中没有名为 "jwtTokenEnhancer" 的 Bean 时,才加载此 Bean
	public TokenEnhancer jwtTokenEnhancer(JwtAccessTokenConverter jwtAccessTokenConverter, JwtProperties jwtProperties) {
		// 创建并返回自定义的 TokenEnhancer
		return new BladeJwtTokenEnhancer(jwtAccessTokenConverter, jwtProperties);
	}
}
对应的自定义类如下:
@AllArgsConstructor  // 自动生成一个包含所有字段的构造函数
public class BladeJwtTokenEnhancer implements TokenEnhancer {
	private final JwtAccessTokenConverter jwtAccessTokenConverter;  // JWT 访问令牌转换器
	private final JwtProperties jwtProperties;  // JWT 配置属性
	@Override
	public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
		// 从身份验证对象中获取用户的详细信息
		BladeUserDetails principal = (BladeUserDetails) authentication.getUserAuthentication().getPrincipal();
		// token 参数增强
		Map<String, Object> info = new HashMap<>(16);  // 创建一个新的 HashMap 用于存储附加信息
		info.put(TokenUtil.CLIENT_ID, TokenUtil.getClientIdFromHeader());  // 获取客户端 ID
		info.put(TokenUtil.USER_ID, Func.toStr(principal.getUserId()));  // 获取用户 ID
		info.put(TokenUtil.DEPT_ID, Func.toStr(principal.getDeptId()));  // 获取部门 ID
		info.put(TokenUtil.POST_ID, Func.toStr(principal.getPostId()));  // 获取职位 ID
		info.put(TokenUtil.ROLE_ID, Func.toStr(principal.getRoleId()));  // 获取角色 ID
		info.put(TokenUtil.TENANT_ID, principal.getTenantId());  // 获取租户 ID
		info.put(TokenUtil.OAUTH_ID, principal.getOauthId());  // 获取 OAuth ID
		info.put(TokenUtil.ACCOUNT, principal.getAccount());  // 获取账户信息
		info.put(TokenUtil.USER_NAME, principal.getUsername());  // 获取用户名
		info.put(TokenUtil.NICK_NAME, principal.getName());  // 获取昵称
		info.put(TokenUtil.REAL_NAME, principal.getRealName());  // 获取真实姓名
		info.put(TokenUtil.ROLE_NAME, principal.getRoleName());  // 获取角色名称
		info.put(TokenUtil.AVATAR, principal.getAvatar());  // 获取用户头像
		info.put(TokenUtil.LICENSE, TokenUtil.LICENSE_NAME);  // 获取许可证名称
		((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);  // 将附加信息设置到访问令牌中
		// token 状态设置
		if (jwtProperties.getState()) {
			// 如果 JWT 状态为 true,则增强访问令牌
			OAuth2AccessToken oAuth2AccessToken = jwtAccessTokenConverter.enhance(accessToken, authentication);
			String tokenValue = oAuth2AccessToken.getValue();  // 获取增强后的 token 值
			String tenantId = principal.getTenantId();  // 获取租户 ID
			String userId = Func.toStr(principal.getUserId());  // 获取用户 ID
			// 将访问令牌存储到 JwtUtil 中,以便后续管理
			JwtUtil.addAccessToken(tenantId, userId, tokenValue, accessToken.getExpiresIn());
		}
		return accessToken;  // 返回增强后的访问令牌
	}
}







![[统计分析] 出现典型锯齿图的一种情况;资源泄露](https://i-blog.csdnimg.cn/direct/44cbae8686db4569a98d803dce3dd4b0.png#pic_center)






![[C++]使用纯opencv部署yolov8-cls图像分类onnx模型](https://i-blog.csdnimg.cn/direct/9baa1cb73ac048cea1cbac6fd15232e9.jpeg)




