Я разрабатываю свой собственный сервер аутентификации Spring Boot и сервер ресурсов, и они работают нормально. Сервер аутентификации предоставляет токен RSW6 JWS, а сервер ресурсов может проверить токен.
Я был очень счастлив и хотел бы знать, что произойдет, если я использую другую пару ключей RSA для проверки токена JWS , Вышло:
org.springframework.security.jwt.crypto.sign.InvalidSignatureException: RSA Signature did not match content
at org.springframework.security.jwt.crypto.sign.RsaVerifier.verify(RsaVerifier.java:55)
at org.springframework.security.jwt.JwtImpl.verifySignature(JwtHelper.java:287)
at org.springframework.security.oauth2.provider.token.store.jwk.JwkVerifyingJwtAccessTokenConverter.decode(JwkVerifyingJwtAccessTokenConverter.java:122)
at org.springframework.security.oauth2.provider.token.store.JwtTokenStore.convertAccessToken(JwtTokenStore.java:88)
at org.springframework.security.oauth2.provider.token.store.JwtTokenStore.readAccessToken(JwtTokenStore.java:80)
at org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore.readAccessToken(JwkTokenStore.java:212)
at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:229)
at org.springframework.security.oauth2.provider.token.DefaultTokenServices$$FastClassBySpringCGLIB$$5a1f25c.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
at org.springframework.security.oauth2.provider.token.DefaultTokenServices$$EnhancerBySpringCGLIB$$14463cf2.loadAuthentication(<generated>)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:83)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
...
и ответ <500 Internal Server Error> с телом:
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">
h1 {
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 22px;
}
h2 {
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 16px;
}
h3 {
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
font-size: 14px;
}
body {
font-family: Tahoma, Arial, sans-serif;
color: black;
background-color: white;
}
b {
font-family: Tahoma, Arial, sans-serif;
color: white;
background-color: #525D76;
}
p {
font-family: Tahoma, Arial, sans-serif;
background: white;
color: black;
font-size: 12px;
}
a {
color: black;
}
a.name {
color: black;
}
.line {
height: 1px;
background-color: #525D76;
border: none;
}
</style>
</head>
<body>
<h1>HTTP Status 500 – Internal Server Error</h1>
</body>
</html>
Я хотел бы обработать эту ошибку в пользовательском JSON тело ошибки или, по крайней мере, выглядит так же, как обычное исключение AuthenticationException
например, <401 не авторизован>
{
"error": "invalid_token",
"error_description": "Invalid JWT/JWS: RSA Signature did not match content"
}
Мои зависимости Spring / Boot:
plugins {
id 'org.springframework.boot' version '2.2.4.RELEASE'
...
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.0.RELEASE")
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.cloud:spring-cloud-starter-sleuth")
compile("org.springframework.security:spring-security-jwt")
...
}
Что я пробовал:
- Обрабатывать
@ControllerAdvice
(Из других ответов в Stackoverflow должен быть запрос, который еще не перешел в MVC, поэтому бесполезен) - Зарегистрируйте пользовательские
AuthenticationEntryPoint
до ResourceServerConfigurerAdapter.configure(HttpSecurity)
(Не знаю, почему это не может помочь, но попытался) - Редактировать
Попробовал предложение от @Jazzepi, Реализация HandlerExceptionResolver
или расширение AbstractHandlerExceptionResolver
с помощью метода:
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof InvalidSignatureException) {
ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
mav.addObject("key", "value");
return mav;
}
return null;
}
И затем попытался зарегистрироваться через WebMvcConfigurator.extendHandlerExceptionResolvers(List<HandleExceptionResolvers>)
(Это не может помочь, все равно выведите тот же ответ, что и выше)
Редактировать:
Как создать и декодировать токен?
В точности следует этому уроку: https://www.baeldung.com/spring-security-oauth2-jws-jwk
Как воспроизвести эту ситуацию?
- Запустить сервер аутентификации и ресурсов.
- Получить токен с сервера аутентификации и один раз используйте токен на сервере ресурсов, чтобы кеш сервера ресурсов опубликовал ключ publi c в локальном
- Измените файл хранилища ключей на сервере аутентификации и перезапустите
- Получить новый токен с перезапущенного сервера аутентификации
- Использование нового токена на сервере ресурсов