首页 > 解决方案 > Spring Boot + JWT:应根据身份验证服务器检查令牌

问题描述

据我了解,JWT 包含标头、有效负载和签名。

签名通过使用秘密加密标头和有效负载来确保 JWT 完整性。

因此,如果身份验证(令牌)服务器和资源服务器共享相同的秘密,则资源服务器应该能够自己验证令牌,这就是这些令牌的目的。

因此,我有两个问题:

[编辑]我自己回答了这个:

事实上,使用 JWT 而不检查令牌存储的主要问题是我们无法撤销它们。仅使用签名来检查其真实性,任何令牌在过期之前都保持有效。

根据令牌存储检查 JWT 允许我们撤销令牌,在这种情况下,将不会接受已被撤销的有效 JWT 来验证请求。

因此,唯一可以安全使用自认证 JWT 的情况是到期时间非常短。

我当前咨询远程令牌服务的资源服务器配置:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Profile("!test")
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${auth-server.url}")
    private String authEndpoint;

    @Value("${security.oauth2.client.client-id}")
    private String clientId;

    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;

    @Override
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId("ms/legacy");
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().permitAll().and().cors().disable().csrf().disable().httpBasic().disable()
        .exceptionHandling()
        .authenticationEntryPoint(
            (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
        .accessDeniedHandler(
            (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED));
  }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("ms/legacy");
    }

    @Bean
    public ResourceServerTokenServices tokenService() {
        RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setClientId(clientId);
        tokenServices.setClientSecret(clientSecret);
        tokenServices.setCheckTokenEndpointUrl(authEndpoint + "/uaa/oauth/check_token");
        return tokenServices;
    }
}

标签: spring-bootspring-securityjwt

解决方案


  • 为什么Spring提供了RemoteTokenServices,不是反模式吗?

Spring 是一个灵活的框架,它将为您提供不同的实现,它让您可以选择最适合您需要的实现。

  • 如果我不使用此服务,如何仅使用密钥在本地实现令牌验证?

本地令牌验证:

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {   

    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        config.tokenServices(tokenServices());
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123");
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }
    }

推荐阅读