介绍
JwtAccessTokenConverter
是 Spring Security OAuth2 中的一个类,用于处理 JWT(JSON Web Token)的生成和验证。它在授权服务器和资源服务器之间起着关键作用,确保令牌的完整性和真实性。
JwtAccessTokenConverter
的角色和作用
在授权服务器中
JwtAccessTokenConverter
用于生成和签名 JWT。- 授权服务器使用私钥对 JWT 进行签名,以确保令牌的完整性和真实性。
在资源服务器中
JwtAccessTokenConverter
用于验证和解码 JWT。- 资源服务器使用公钥验证 JWT 的签名,以确保令牌未被篡改,并从中提取相关的声明(claims)。
JwtAccessTokenConverter
的具体功能
-
令牌转换(Token Conversion):
- 将 OAuth2 访问令牌转换为 JWT。
- 将 JWT 解码为 OAuth2 访问令牌。
-
签名和验证(Signing and Verification):
- 在授权服务器中使用私钥对 JWT 进行签名。
- 在资源服务器中使用公钥验证 JWT 的签名。
授权服务器、资源服务器和 JwtAccessTokenConverter
之间的关系
授权服务器
授权服务器负责认证用户并颁发令牌。配置授权服务器时,会使用 JwtAccessTokenConverter
来生成和签名 JWT。示例配置如下:
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import java.security.KeyPair;
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
new ClassPathResource("cxs-jwt.jks"), "cxs123".toCharArray())
.getKeyPair("cxs-jwt");
converter.setKeyPair(keyPair);
return converter;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
}
资源服务器
资源服务器保护资源,并在每个请求中验证 JWT 的有效性。配置资源服务器时,也会使用 JwtAccessTokenConverter
来验证 JWT 的签名。示例配置如下
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.TokenStore;
import java.io.IOException;
import java.nio.charset.Charset;
public class ResourceConfig extends ResourceServerConfigurerAdapter {
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
ClassPathResource resource = new ClassPathResource("jwt-publicKey.txt");
try {
String publicKey = FileUtil.readString(resource.getFile(), Charset.defaultCharset());
jwtAccessTokenConverter.setVerifierKey(publicKey);
} catch (IOException e) {
e.printStackTrace();
}
return jwtAccessTokenConverter;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore());
}
}
工作流程
-
客户端请求令牌:
- 客户端(如 Web 应用或移动应用)向授权服务器请求访问令牌。
- 授权服务器认证客户端身份,并生成 JWT。
JwtAccessTokenConverter
使用私钥对 JWT 进行签名。- 签名后的 JWT 返回给客户端。
-
客户端请求受保护资源:
- 客户端使用 JWT 请求资源服务器的受保护资源。
- 资源服务器接收到 JWT,并使用
JwtAccessTokenConverter
进行解码和签名验证。 JwtAccessTokenConverter
使用公钥验证 JWT 的签名。- 如果签名验证通过,资源服务器允许访问受保护资源;如果验证失败,拒绝访问。
具体方法解释
configure(AuthorizationServerEndpointsConfigurer endpoints)
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter());
}
-
tokenStore(tokenStore())
:- 指定用于存储令牌的策略。在这里使用
JwtTokenStore
。 JwtTokenStore
是一个TokenStore
的实现,用于存储 JWT。
- 指定用于存储令牌的策略。在这里使用
-
accessTokenConverter(accessTokenConverter())
:- 指定用于访问令牌转换的策略。在这里使用
JwtAccessTokenConverter
。 JwtAccessTokenConverter
用于将 OAuth2 访问令牌转换为 JWT,并在授权服务器中使用私钥对 JWT 进行签名。
- 指定用于访问令牌转换的策略。在这里使用
configure(AuthorizationServerSecurityConfigurer security)
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
这段代码的作用是配置授权服务器的安全性,具体包括以下两方面:
-
tokenKeyAccess("permitAll()")
:- 允许所有人访问令牌密钥端点。
- 通常,这个端点提供的是公钥,客户端和资源服务器可以通过这个端点获取公钥,用于验证 JWT 的签名。
- 公开访问公钥是安全的,因为公钥仅用于验证签名,而不能用于生成签名。
-
checkTokenAccess("isAuthenticated()")
:- 要求对令牌检查的访问需要身份验证。
- 这意味着只有经过认证的客户端才能访问检查令牌的端点,确保只有合法的客户端可以进行令牌验证请求。
运行流程
-
令牌生成和存储:
- 客户端请求令牌时,授权服务器使用
JwtAccessTokenConverter
生成 JWT,并存储在JwtTokenStore
中。
- 客户端请求令牌时,授权服务器使用
-
公钥访问:
- 客户端或资源服务器可以访问
/oauth/token_key
端点获取公钥,用于验证 JWT 的签名。
- 客户端或资源服务器可以访问
-
令牌检查:
- 客户端或资源服务器可以访问
/oauth/check_token
端点检查令牌的有效性,但必须经过身份验证才能访问该端点。
- 客户端或资源服务器可以访问
总结
configure(AuthorizationServerEndpointsConfigurer endpoints)
配置了授权服务器的端点,指定了如何存储和转换令牌。configure(AuthorizationServerSecurityConfigurer security)
配置了授权服务器的安全性,定义了公钥访问和令牌检查的访问规则。
这些配置确保了授权服务器能够安全地生成和管理 JWT,并提供必要的端点供客户端和资源服务器访问。