Spring找不到身份验证令牌的提供者

时间:2019-04-06 12:16:18

标签: java spring kotlin spring-security spring-webflux

我编写了一些自定义身份验证逻辑,其中包括一个自定义抽象身份验证令牌。我登录,获取了我的JWT,并尝试使用该JWT访问资源。然后该程序在身份验证期间抛出了一个异常(确切地说是在身份验证管理器中),告诉我它无法通过自定义身份验证令牌找到提供程序。

我尝试使用Springs内置的身份验证令牌(例如UsernamePasswordAuthenticationToken)代替我的自定义令牌,但是收效甚微。除了现在的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]

如果您曾经遇到过此问题并已解决它,或者您发现我的代码有问题,我将很高兴听到它。预先感谢。

0 个答案:

没有答案