Я использую Spring Boot 2.1.5 и создаю два отдельных модуля для Сервера авторизации и Сервера ресурсов.Недавно я переключился на использование JWT вместо обычных токенов доступа, используя примеры, показанные здесь и здесь .
Теперь ошибка, которая меня здесь привела, это
Caused by: java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
Я посмотрел на этот ответ , но это не так со мной.Я сгенерировал нужные файлы с помощью keytool и сохранил их в своей папке ресурсов.
- JKS-файл в папке ресурсов модуля сервера авторизации
- public_key.txt в папке ресурсов на сервере ресурсов.module
Вот мой файл конфигурации сервера авторизации
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(AuthorizationServerConfiguration.class);
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DataSource dataSource;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(this.dataSource);
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(
Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.tokenEnhancer(tokenEnhancerChain)
.accessTokenConverter(jwtAccessTokenConverter())
.tokenStore(tokenStore());
}
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.passwordEncoder(passwordEncoder).tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(new ClassPathResource("accesstoken_keystore.jks"), "my-keystore-password".toCharArray());
jwtAccessTokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("my-alias"));
return jwtAccessTokenConverter;
}
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public DefaultTokenServices tokenServices(final TokenStore tokenStore,
final ClientDetailsService clientDetailsService) {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
tokenServices.setClientDetailsService(clientDetailsService);
tokenServices.setAuthenticationManager(authenticationManager);
return tokenServices;
}
}
А вот мой класс конфигурации сервера ресурсов
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(ResourceServerConfig.class);
@Autowired
private Environment env;
@Autowired
private CustomAccessTokenConverter accessTokenConverter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('read')")
.anyRequest().authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
@Override
public void configure(ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices());
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
Resource publicKeyResource = new ClassPathResource("public_key.txt");
String publicKey = null;
try {
publicKey = new String(FileCopyUtils.copyToByteArray(publicKeyResource.getInputStream()));
} catch (final IOException e) {
throw new RuntimeException(e);
}
converter.setVerifierKey(publicKey); //this is where I'm getting the error
return converter;
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
}
А вот содержимое public_keyФайл .txt в том виде, как он есть
-----BEGIN PUBLIC KEY-----
blah blah blah
blah blah blah
-----END PUBLIC KEY-----
Я ожидаю, что Сервер авторизации подпишет JWT с помощью Закрытого ключа, извлеченного из файла KeyStore, а Ресурсный Сервер просто проверит его.
Не уверен, что не так.Все работало нормально, прежде чем я решил использовать асимметричную пару ключей RSA.