资源服务器验证Token的几种方式

资源服务器验证Token的几种方式

在微服务中,除了eureka,config,网关等基本的微服务还有认证服务和资源服务,

上图描述了使用了 OAuth2 的客户端请求验证token的流程,是通过资源服务向认证服务验证token。

过程就是客户端用用户名和密码到认证服务获取token,客户端拿着 token 去各个微服务请求数据接口,

当微服务接到请求后,先要拿着 token 去认证服务校验token 的合法性,如果合法,请求成功接口处理返回数据。

这种方式首先要在认证服务的认证服务配置允许验证token,其是通过调用认证服务的/oauth/check_token接。

方式一资源服务远程调用认证服务验证Token

认证服务需要在AuthorizationServerConfigurerAdapter继承类中配置中增加以下代码,允许资源服务调用校验

token的接口。

@Override
public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {

    security.allowFormAuthenticationForClients();
    security.checkTokenAccess("isAuthenticated()");
}

资源服务的配置文件如下,http://localhost:3000/oauth/check_token是接到请求向认证服务校验的接口。

security:
  oauth2:
    client:
      clientId: client
      clientSecret: secret
      access-token-uri: http://localhost:3000/oauth/token
      user-authorization-uri: http://localhost:3000/oauth/authorize
    resource:
      user-info-uri: http://localhost:3000/user
      prefer-token-info: false
      #jwt:
      #  key-uri: http://localhost:32002/oauth/token_key
      id: cpms-resource-user
    authorization:
      check-token-access: http://localhost:3000/oauth/check_token

资源服务需要在ResourceServerConfigurerAdapter继承类中新增以下代码,配置校验token的地址

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {

        http.headers().frameOptions().disable().and().csrf().disable().exceptionHandling()
                .authenticationEntryPoint(
                        (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)
                .antMatchers("/user/register", "/v2/api-docs", "/swagger-ui/**")
                .permitAll().anyRequest().authenticated();
    }

    @Override
    public void configure(final ResourceServerSecurityConfigurer resources) throws Exception {

        super.configure(resources);
        resources.tokenServices(tokenService());
    }

    //资源服务令牌解析服务
    @Bean
    public ResourceServerTokenServices tokenService() {
        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
        final RemoteTokenServices service = new RemoteTokenServices();
        service.setCheckTokenEndpointUrl("http://localhost:3000/oauth/check_token");
        service.setClientId("client");
        service.setClientSecret("secret");
        return service;
    }
    
}

以上方式每次请求资源服务都需要向认证服务校验,增加了网络开销。

方式二资源服务启动调用/oauth/token_key接口初始化tokenstore(一般默认方式)

另外一种校验方式就是资源服务自己校验token,也就是资源服务拿到token后,根据已知的算法和签名密钥去校验token,这种方式减少了网络开销。认证服务需要在AuthorizationServerConfigurerAdapter集成类中配置中修改以下代码,允许资源服务访问认证服务获取token算法和签名密钥的接口。

@Override
public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {

    security.tokenKeyAccess("permitAll()");
    security.allowFormAuthenticationForClients();

}

因此资源服务的配置需要修改,将token_key接口的注释打开。

security:
  oauth2:
    client:
      clientId: client
      clientSecret: secret
      access-token-uri: http://localhost:3000/oauth/token
      user-authorization-uri: http://localhost:3000/oauth/authorize
    resource:
      user-info-uri: http://localhost:3000/user
      prefer-token-info: false
      jwt:
         key-uri: http://localhost:32002/oauth/token_key
      id: cpms-resource-user
    authorization:
      check-token-access: http://localhost:3000/oauth/check_token

修改资源服务的ResourceServerConfigurerAdapter继承类,只需要以下代码。

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {

        http.headers().frameOptions().disable().and().csrf().disable().exceptionHandling() 
            .authenticationEntryPoint( (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED) 
            .antMatchers("/user/register", "/v2/api-docs", "/swagger-ui/**") .permitAll().anyRequest().authenticated();
    }
   
}

资源服务启动时会调用/oauth/token_key接口,获取token加密算法和签名密钥,拿到这些信息后初始化tokenstore等Bean。完成启动后客户端带token的请求到资源服务器,资源服务器会通过相关过滤器进行token校验,这里就不展开了。这里资源服务启动需要依赖于认证服务,认证服务启动后才能启用资源服务,否则资源服务启动不了。资源服务启动后认证服务打印的日志如下图所示。

接口返回的token算法和签名密钥如下图所示

方式三资源服务配置token相关的Bean

方式二是资源服务自己校验token,依赖于认证服务才能启动,方式三其实和方式二一样,同样是自己校验token,但是区别在于启动时不需要去认证服务调用/oauth/token_key接口,不依赖域认证服务启动。只需要针对资源服务配置做以下修改,配置TokenStore的Bean。

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

        @Override
    public void configure(final HttpSecurity http) throws Exception {

        http.headers().frameOptions().disable().and().csrf().disable().exceptionHandling() 
            .authenticationEntryPoint( (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED) 
            .antMatchers("/user/register", "/v2/api-docs", "/swagger-ui/**") .permitAll().anyRequest().authenticated();
    }

    @Bean
    public TokenStore jwtTokenStore() {

        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean

    public JwtAccessTokenConverter jwtAccessTokenConverter() {

        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setAccessTokenConverter(new CustomAccessTokenConverter());
        converter.setSigningKey("和认证服务一样的signkey");
        return converter;
    }


    @Bean
    @ConditionalOnBean(TokenEnhancer.class)
    public TokenEnhancer jwtTokenEnhancer() {

        return new TokenJwtEnhancer();
    }
}

以上就是资源服务验证token的三种方式,第一种方式是远程验证token,每个请求到来都要拿着token去请求认证服务进行验证,增加了网络开销。第二种方式是配置文件中配置/oauth/token_key接口,服务启动时调用该接口获取token算法和签名密钥,完成TokenStore初始化,该方式不需要任何代码配置,但是依赖认证服务启动。方式三在资源服务ResourceServerConfig配置了token相关的Bean,在服务启动时完成初始化Bean,不需要去调用认证服务获取相关算法和签名密钥,其原理和方式二基本一致,但启动不依赖于认证服务。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值