#spring-boot #kotlin #spring-security #jwt
Вопрос:
Я следовал этому руководству, чтобы получить аутентификацию на основе jwt в моем приложении spring boot: https://octoperf.com/blog/2018/03/08/securing-rest-api-spring-security Однако я использую Kotlin.
Согласно учебнику, я добавил a TokenAuthenticationFilter
, который распространяется AbstractAuthenticationProcessingFilter
на цепочку фильтров в WebSecurityConfigurerAdapter
.
override fun configure(http: HttpSecurity) = http.apply {
//...
authenticationProvider(authProvider)
addFilterBefore(tokenAuthFilter, SecurityContextHolderAwareRequestFilter::class.java)
//...
В successfulAuthentication
методе этот фильтр правильно установит учетные данные:
SecurityContextHolder.getContext().setAuthentication(authResult);
Цепочка фильтров выполняется для методов в контроллерах без защиты методов.
Вход в систему работает, я получаю токен jwt, и когда я помещаю его в заголовок авторизации запросов, я получаю надлежащую аутентификацию, поэтому тестирование с конечной точкой я успешно возвращаю вошедшего пользователя
@GetMapping("/")
fun whoami(@AuthenticationPrincipal user: User?) = user;
Однако, как только я попытаюсь использовать безопасность метода на какой-либо конечной точке
@PostMapping("/upload")
@PreAuthorize("hasAuthority('UploadArtifact')")
fun uploadArtifact(
@RequestParam("artifact", required = true) artifact: MultipartFile,
@Valid @RequestParam("meta", required = true) request: UploadArtifactRequest
): ResponseEntity<Any> {
//...
Я получаю исключение authenticationкредитальснотпоиск
организация.каркасная работа.безопасность.аутентификация.Исключение AuthenticationCredentialsNotFoundException: Объект проверки подлинности не был найден в контексте безопасности в org.springframework.security.access.intercept.AbstractSecurityInterceptor.Учетные данные не найдены(AbstractSecurityInterceptor.java:333) ~[spring-security-core-5.5.0.jar:5.5.0] в организации. springframework.безопасность.доступ.перехват.AbstractSecurityInterceptor.Перед вызовом(AbstractSecurityInterceptor.java:200) ~[spring-security-core-5.5.0.jar:5.5.0] в организации.каркасная работа.безопасность.доступ.перехват.альянс.MethodSecurityInterceptor.вызовите(MethodSecurityInterceptor.java:58) ~[spring-security-core-5.5.0.jar:5.5.0] в org.springframework.aop.framework.Рефлексивный метод вызова.продолжайте(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.8.jar:5.3.8] в org.springframework.aop.framework.Cglibopproxy$Вызов cglibmethod.продолжайте(CglibEopProxy.java:750) ~[spring-aop-5.3.8.jar:5.3.8] в org.springframework.aop.framework.CglibEopProxy$DynamicAdvisedInterceptor.перехватить(CglibEopProxy.java:692) ~[spring-aop-5.3.8.jar:5.3.8] в [###имя пакета отредактировано###].ArtifactController$$EnhancerBySpringCGLIB$$99d39dee.uploadArtifact() ~[main/:na] …
I set breakpoints
- at the start of the
TokenAuthenticationFilter.successfulAuthentication
method. - in
ApplicationFilterChain.doFilter
Apparently two ApplicationFilterChain
instances run on the request, both of which containa delegating proxy chain named ‘springSecurityFilterChain’
- The
ApplicationFilterChain
that is executed first is started fromStandardWrapperValve.java
.
Its springSecurityFilterChain does not contain the TokenAuthenticationFilter . The AuthenticationCredentialsNotFoundException exception is thrown here. - The second
ApplicationFilterChain
is started fromApplicationDispatcher.java
.
Its springSecurityFilterChain does contain theTokenAuthenticationFilter
and successfulAuthentication is reached, but that is obviousely useless at that point.
So now I have two independent questions:
- Как я могу гарантировать, что аутентификация произойдет вовремя? Должны ли быть две цепочки фильтров — или я что-то напутал с настройкой?
- в целом: должен ли я вообще использовать такой учебник — или есть лучший способ интегрировать проверку подлинности без сохранения состояния с jwt в 2021 году в приложение spring boot?