使用refrest令牌时,Spring Boot JWT令牌无效签名

时间:2019-10-15 15:07:10

标签: spring spring-boot spring-security oauth jwt

因此,我正在构建OAuth服务器。

我可以正常打我的授权服务器,但是签名似乎无效。

将其插入https://jwt.io/会导致签名无效。更糟糕的是,当我尝试使用刷新令牌时,我收到InvalidTokenException,无法将访问令牌转换为JSON。

这秘密地来自JwtAccessTokenConverter.java

protected Map<String, Object> decode(String token) {
        try {
            Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
            String claimsStr = jwt.getClaims();
            Map<String, Object> claims = objectMapper.parseMap(claimsStr);
            if (claims.containsKey(EXP) && claims.get(EXP) instanceof Integer) {
                Integer intValue = (Integer) claims.get(EXP);
                claims.put(EXP, new Long(intValue));
            }
            this.getJwtClaimsSetVerifier().verify(claims);
            return claims;
        }
        catch (Exception e) {
            throw new InvalidTokenException("Cannot convert access token to JSON", e);
        }
    }

真正的例外是计算出的签名与给定的签名不匹配。因此由于某种原因,签名实际上并未对所有内容进行签名。我有一个自定义令牌增强器,可以放置几个额外的值。我怀疑这没有得到签名,不是我知道为什么。

下面是我的授权服务器

@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(SecurityProperties::class)
class AuthorizationServerConfiguration(private val dataSource: DataSource, private val passwordEncoder: PasswordEncoder,
                                       private val authenticationManager: AuthenticationManager, private val securityProperties: SecurityProperties,
                                       private val userDetailsService: UserDetailsService) : AuthorizationServerConfigurerAdapter() {

    private var jwtAccessTokenConverter: JwtAccessTokenConverter? = null
    private var tokenStore: TokenStore? = null

    @Bean
    fun tokenEnhancer(): CustomTokenEnhancer {
        return CustomTokenEnhancer()
    }

    @Bean
    fun loggingExceptionTranslator(): DefaultWebResponseExceptionTranslator {
        return object : DefaultWebResponseExceptionTranslator() {
            @Throws(Exception::class)
            override fun translate(e: Exception): ResponseEntity<OAuth2Exception> {
                // This is the line that prints the stack trace to the log. You can customise this to format the trace etc if you like
                e.printStackTrace()

                // Carry on handling the exception
                val responseEntity = super.translate(e)
                val headers = HttpHeaders()
                headers.setAll(responseEntity.headers.toSingleValueMap())
                val excBody = responseEntity.body
                return ResponseEntity(excBody, headers, responseEntity.statusCode)
            }
        }
    }

    @Bean
    fun tokenStore(): TokenStore {
        if (tokenStore == null) {
            tokenStore = JwtTokenStore(tokenEnhancer())
        }
        return tokenStore as TokenStore
    }

    @Bean
    fun tokenServices(tokenStore: TokenStore,
                      clientDetailsService: ClientDetailsService): DefaultTokenServices {
        val tokenServices = DefaultTokenServices()
        tokenServices.setSupportRefreshToken(true)
        tokenServices.setTokenStore(tokenStore)
        tokenServices.setAuthenticationManager(this.authenticationManager)
        tokenServices.setAccessTokenValiditySeconds(securityProperties.tokenTimeToLive)
        return tokenServices
    }

    @Bean
    fun jwtAccessTokenConverter(): JwtAccessTokenConverter {
        if (jwtAccessTokenConverter != null) {
            return jwtAccessTokenConverter as JwtAccessTokenConverter
        }

        val jwtProperties = securityProperties.jwt
        val keyPair = jwtProperties?.let { keyStoreKeyFactory(it) }?.let { keyPair(jwtProperties, it) }
        jwtAccessTokenConverter = CustomTokenEnhancer()
        jwtAccessTokenConverter!!.setKeyPair(keyPair!!)
        jwtAccessTokenConverter!!.afterPropertiesSet()
        return jwtAccessTokenConverter as JwtAccessTokenConverter
    }

    @Throws(Exception::class)
    override fun configure(clients: ClientDetailsServiceConfigurer) {
        clients.jdbc(this.dataSource)
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
        endpoints.authenticationManager(this.authenticationManager)
                .accessTokenConverter(jwtAccessTokenConverter())
                .userDetailsService(this.userDetailsService)
                .tokenStore(tokenStore())
    }

    override fun configure(oauthServer: AuthorizationServerSecurityConfigurer) {
        oauthServer.passwordEncoder(this.passwordEncoder).tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
    }

    private fun keyPair(jwtProperties: SecurityProperties.JwtProperties?, keyStoreKeyFactory: KeyStoreKeyFactory): KeyPair {
        return keyStoreKeyFactory.getKeyPair(jwtProperties?.keyPairAlias, jwtProperties?.keyPairPassword?.toCharArray())
    }

    private fun keyStoreKeyFactory(jwtProperties: SecurityProperties.JwtProperties): KeyStoreKeyFactory {
        return KeyStoreKeyFactory(jwtProperties.keyStore, jwtProperties.keyStorePassword?.toCharArray())
    }
}

1 个答案:

答案 0 :(得分:0)

我需要在下一行中使用

@Bean
fun tokenStore(): TokenStore {
    return JwtTokenStore(jwtAccessTokenConverter())
}