【发布时间】:2023-01-01 12:36:20
【问题描述】:
我自定义授权服务器以将自定义详细信息添加到 JSON Web 令牌,并希望资源服务器应使用端点访问授权服务器上的验证程序公钥。但是 OAuth2AuthenticationDetails.getDecodedDetails() 返回 null。
我的代码结构如下所示:
自定义令牌增强器类:
public class CustomTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken oauth2AccessToken,
OAuth2Authentication oauth2Authentication) {
var customToken = new DefaultOAuth2AccessToken(oauth2AccessToken);
Map<String, Object> customInfo = Map.of("generatedIn", "Year "+LocalDateTime.now().getYear());
customToken.setAdditionalInformation(customInfo);
return customToken;
}
}
授权服务器类:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter{
@Value("${password}")
private String password;
@Value("${privateKey}")
private String privateKey;
@Value("${alias}")
private String alias;
//autowire the authentication manager here
@Autowired
private AuthenticationManager authenticationManager;
//provide clients' details
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.secret("secret")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read")
.and()
.withClient("resourceserver")
.secret("resourceserversecret");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
//Define a token enhancer chain here
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//Add the two token enhancer objects to a list
var tokenEnhancers =
List.of(new CustomTokenEnhancer(), jwtAccessTokenConverter());
//Add the token enhancer list to the chain of token enhancer
tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
/*
* Configures the authorization server to expose and endpoint for
* public key for any authenticated
* request with valid client credentials
*/
security.tokenKeyAccess("isAuthenticated()");
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
var converter = new JwtAccessTokenConverter();
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(
new ClassPathResource(privateKey),
password.toCharArray()
);
converter.setKeyPair(keyStoreKeyFactory.getKeyPair(alias));
return converter;
}
}
应用程序.properties 文件:
password = somepassword
privateKey =key.jks
alias = somekey
资源服务器:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
}
应用程序.properties 文件:
server.port = 9090
security.oauth2.resource.jwt.key-uri=http://localhost:8080/oauth/token_key
security.oauth2.client.client-id=resourceserver
security.oauth2.client.client-secret=resourceserversecret
资源服务器上的受保护端点:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(OAuth2Authentication authentication) {
OAuth2AuthenticationDetails details =
(OAuth2AuthenticationDetails) authentication.getDetails();
return details.getDecodedDetails().toString();
}
}
当我发出 curl 请求时,调用 details.getDecodedDetails().toString() 的结果将 null 打印到控制台:curl -H "Authorization:Bearer e1yhrjkkkfk....." http://localhost:9090/hello。
但是,如果我像这样实现资源服务器,代码将按预期运行:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter{
@Value("${publicKey}") //from the properties file
private String publicKey;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
var converter = new OtherAccessTokenConverter(); //Handles the claims in our custom token.
converter.setVerifierKey(publicKey);
return converter;
}
}
OtherAccessTokenConverter类:
public class OtherAccessTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
//Get the initial authenticated object
var authentication = super.extractAuthentication(map);
//Add the custom details to the authentication object
authentication.setDetails(map);
//Return the authentication object
return authentication;
}
但我从来不想在资源服务器上拥有公共验证器密钥,而是通过端点访问。我该怎么做?
【问题讨论】: