Я написал некоторую пользовательскую логику аутентификации, включая собственный токен абстрактной аутентификации.Я вошел в систему, получил свой JWT и попытался получить доступ к ресурсу с этим JWT.Затем программа выдавала исключение во время аутентификации (если быть точным, в менеджере аутентификации), сообщая, что не может найти провайдера по токену аутентификации.
Я пытался использовать встроенные токены аутентификации Springs, такие какИмя пользователяPasswordAuthenticationToken вместо моего пользовательского, но с небольшим успехом.Я получаю то же исключение, за исключением теперь для UsernamePasswordAuthenticationToken.
Основной класс конфигурации безопасности
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
class WebFluxSecurityConfig {
@Autowired
private lateinit var jwtProvider: JWTProvider
@Autowired
private lateinit var userRepository: UserRepository
fun tokenAuthenticationConverter() = ServerAuthenticationConverter {
val authorization = it.request.headers.getFirst(HttpHeaders.AUTHORIZATION)
if (authorization == null || !authorization.startsWith("Bearer "))
Mono.empty<Authentication>()
else
Mono.just<Authentication>(JWTAuthenticationToken(authorization.substring(7)))
}
fun tokenAuthenticationManager() = ReactiveAuthenticationManager {
val jwt = it.credentials as String
if (jwtProvider.validateJWT(jwt))
userRepository
.findById(jwtProvider.getUserIdFromJWT(jwt))
.map<Authentication> { user ->
val userDetails = UserPrincipal(user)
JWTAuthenticationToken(
userDetails,
jwt,
userDetails.authorities
)
}
else
throw InvalidJWTException("JWT could not be validated")
}
fun tokenAuthenticationFilter(): AuthenticationWebFilter {
val filter = AuthenticationWebFilter(tokenAuthenticationManager())
filter.setServerAuthenticationConverter(tokenAuthenticationConverter())
filter.setAuthenticationFailureHandler { _, exception -> Mono.error(exception) }
return filter
}
@Bean
fun securityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
return http
.csrf()
.disable()
.logout()
.disable()
.authorizeExchange()
.pathMatchers("/login")
.permitAll()
.anyExchange()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.authenticationFailureHandler { _, exception -> Mono.error(exception) }
.authenticationSuccessHandler(WebFilterChainServerAuthenticationSuccessHandler())
.and()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.exceptionHandling()
.authenticationEntryPoint { _, exception -> Mono.error(exception) }
.accessDeniedHandler { _, exception -> Mono.error(exception) }
.and()
.addFilterAt(tokenAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.build()
}
@Bean
fun passwordEncoder(): PasswordEncoder {
return PasswordEncoderFactories.createDelegatingPasswordEncoder()
}
}
Пользовательский токен аутентификации
class JWTAuthenticationToken(
authorities: MutableCollection<out GrantedAuthority>
): AbstractAuthenticationToken(authorities) {
private var userDetails: UserDetails? = null
private lateinit var jwt: String
constructor(): this(
AuthorityUtils.NO_AUTHORITIES
)
constructor(jwt: String): this(
AuthorityUtils.NO_AUTHORITIES
) {
this.jwt = jwt
}
constructor(userDetails: UserDetails, jwt: String, authorities: MutableCollection<out GrantedAuthority>): this(
authorities
) {
this.jwt = jwt
this.userDetails = userDetails
isAuthenticated = true
}
override fun getCredentials(): Any {
return jwt
}
override fun getPrincipal(): Any? {
return userDetails
}
}
Вот стек вызовов
java.lang.IllegalStateException: No provider found for class ch.jb.notes.note.security.JWTAuthenticationToken
at org.springframework.security.web.server.authentication.AuthenticationWebFilter.lambda$authenticate$3(AuthenticationWebFilter.java:99) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.Mono.subscribe(Mono.java:3694) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:75) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:1742) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.FluxHide$SuppressFuseableSubscriber.onComplete(FluxHide.java:137) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at reactor.core.publisher.MonoNext$NextSubscriber.onComplete(MonoNext.java:96) ~[reactor-core-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1.onComplete(ObservableToPublisher.java:78) ~[mongodb-driver-reactivestreams-1.9.2.jar:na]
at com.mongodb.async.client.AbstractSubscription.onComplete(AbstractSubscription.java:145) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.AbstractSubscription.processResultsQueue(AbstractSubscription.java:211) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.AbstractSubscription.tryProcessResultsQueue(AbstractSubscription.java:159) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.SingleResultCallbackSubscription$1.onResult(SingleResultCallbackSubscription.java:48) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.FindIterableImpl$1$1.onResult(FindIterableImpl.java:211) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.FindIterableImpl$1$1.onResult(FindIterableImpl.java:204) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:141) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:100) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.async.client.FindIterableImpl$1.onResult(FindIterableImpl.java:204) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.async.client.FindIterableImpl$1.onResult(FindIterableImpl.java:198) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.async.client.OperationExecutorImpl$1$1.onResult(OperationExecutorImpl.java:82) ~[mongodb-driver-async-3.8.2.jar:na]
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.operation.FindOperation$3.onResult(FindOperation.java:806) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:364) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.operation.CommandOperationHelper$2.onResult(CommandOperationHelper.java:405) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor$2.onResult(DefaultServer.java:227) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.CommandProtocolImpl$1.onResult(CommandProtocolImpl.java:85) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:461) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.UsageTrackingInternalConnection$2.onResult(UsageTrackingInternalConnection.java:111) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:379) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:356) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:651) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:618) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:494) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:491) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:236) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:491) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection.access$1000(InternalStreamConnection.java:74) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:608) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:593) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:494) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:491) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:236) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream.handleReadResponse(NettyStream.java:266) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream.access$600(NettyStream.java:66) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:325) ~[mongodb-driver-core-3.8.2.jar:na]
at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:322) ~[mongodb-driver-core-3.8.2.jar:na]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:677) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:612) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:529) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:491) ~[netty-transport-4.1.33.Final.jar:4.1.33.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) ~[netty-common-4.1.33.Final.jar:4.1.33.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.33.Final.jar:4.1.33.Final]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Если вы когда-нибудь сталкивались с этой проблемой и решили ее, или если вы видите какую-то проблему с моим кодом, я был бы рад услышать об этом.Заранее спасибо.