java - Spring-boot资源服务器仅在过期时验证 token

标签 java spring spring-boot oauth-2.0

我正在使用 spring-boot 开发一个微服务结构,这个结构有一个外部 oauth2 授权服务器和多个资源服务器。

我的问题是,每个对我的资源的 http 请求都会调用一个 url 到我的授权服务器,以验证 token (.../oauth/check_token/)。这种方式有很多请求。有一种方法可以仅在 token 过期时验证/检查此 token 吗?

我的资源服务器:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    @Value("${security.oauth2.client.client-id}")
    private String clientId;
    
    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;
    
    @Value("${security.oauth2.resource.id}")
    private String resourceId;
    
    @Value("${security.oauth2.resource.token-info-uri}")
    private String tokenInfoUri;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers(ADMIN_ANT_MATCHER).hasRole("ADMIN")
            .antMatchers(PROTECTED_ANT_MATCHER).hasRole("USER")
            .and()
            .csrf().disable();
    }
    
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
         resources.tokenServices(tokenService()).resourceId(resourceId).stateless(true);
    }
    
    @Bean
    @Primary
    public RemoteTokenServices tokenService() {
        RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl(tokenInfoUri);
        tokenService.setClientId(clientId);
        tokenService.setClientSecret(clientSecret);
        return tokenService;
    }
}

授权服务器:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

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

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

    @Value("${security.oauth2.resource.id}")
    private String resourceId;

    @Value("${security.oauth2.client.access-token-validity-seconds}")
    private Integer tokenValidateSeconds;

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

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private OauthAccessTokenRepository oauthAccessTokenRepository;

    @Autowired
    private OauthRefreshTokenRepository oauthRefreshTokenRepository;


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(this.tokenStore)
                .tokenEnhancer(tokenEnhancer())
                .authenticationManager(this.authenticationManager)
                .userDetailsService(userDetailsService);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient(clientId)
                .authorizedGrantTypes("client_credentials", "password", "refresh_token")
                .authorities("ROLE_USER","ROLE_ADMIN")
                .scopes("read","write","trust")
                .resourceIds(resourceId)
                .accessTokenValiditySeconds(tokenValidateSeconds)
                .secret(bCryptPasswordEncoder().encode(clientSecret));
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

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

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new TokenEnhancer() {
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                CustomUser user = (CustomUser) authentication.getPrincipal();

                String token = JwtTokenHelper.generateToken(
                        user.getIdUser(),
                        user.getTenantID(),
                        user.getIdEntity(),
                        user.getIdBusinessUnit(),
                        user.getProfile(),
                        tokenValidateSeconds,
                        tokenSecret
                );

                ((DefaultOAuth2AccessToken) accessToken).setValue(token);

                return accessToken;
            }
        };

    }
}

最佳答案

您可以删除使用 check_token endpoint 的需要, 通过使用签名 JWT代币。

当资源服务器收到 JWT token 时,它会使用公钥验证其签名,并通过检查 JSON 对象中的相应字段来验证到期日期。

为此,您可以使用 JwtAccessTokenConverter , JwtTokenStorenimbus-jose-jwt图书馆。

这种方法的缺点是您无法撤销 token 。最好使用短期 token 。

关于java - Spring-boot资源服务器仅在过期时验证 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66499647/

相关文章:

mysql - 如何更正sql语句以给出正确的结果

java - 使用 Eclipse 进行 GWT 客户端调试

java - 找不到 Spring Boot 2 包

mysql - 由于数据库访问凭据错误,Spring Boot War打包失败

java - 尝试使用 Thymeleaf 处理模板时出错

spring webflow,评估表达式在转换中被忽略

java - Katharsis 结合 Spring Boot

java - IntelliJ 运行配置环境变量未出现在 System.getenv 中

java - 将 arraylist 的值插入数据库

java - 如何在 Apache Tomcat 中初始化 Web 应用程序?