【问题标题】:Spring Boot JWT tokens invalid signature when using refrest token使用刷新令牌时 Spring Boot JWT 令牌无效签名
【发布时间】:2020-02-12 07:35:23
【问题描述】:

所以我正在构建一个 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())
    }
}

【问题讨论】:

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


    【解决方案1】:

    我需要在以下行中使用 bean

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

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 2021-01-19
      • 2017-05-30
      • 2017-10-15
      • 2017-10-27
      • 1970-01-01
      • 2019-09-28
      • 2018-03-16
      • 2019-07-01
      相关资源
      最近更新 更多