如何在Spring中向端点发出客户端ID和密码授权请求?

时间:2017-12-15 06:55:49

标签: spring-boot spring-security oauth

默认情况下,在Spring框架中启用OAuth2授权(请参阅下面的配置)并调用/oauth/token来发出访问令牌时,会发送以下请求:

POST /oauth/token
Authorization: Basic Y34tcF9ib3VpOg==

POST data:
grant_type=password&username=myuser&password=mypass

上面的基本授权是客户ID和客户的秘密,格式如下:

myclient:secret123

然后我可以将此请求发送到Spring的/oauth/check_token

POST /oauth/check_token
Authorization: Basic Y34tcF9ib3VpOg==

POST data:
token=the_token_retrieved_from_last_request

这样可以正常工作,并且在提出请求之前会进行基本授权。

请注意,这里的基本授权是Spring JdbcClientDetailsService,在其中查找名为oauth_client_details的表,这也很好。

现在由于某种原因,我需要一个自定义的端点,而不是Spring的/ token / check_access。所以我创建了一个类似于Spring CheckTokenEndpoint.java的控制器,并命名为TokenIntrospectionEndpoint。我的端点的网址格式设置为/oauth/introspect

@Controller
@RequestMapping("/oauth")
public class TokenIntrospectionEndpointImpl {

    private RestTemplate restTemplate;

    @RequestMapping(value = "/introspect")
    @ResponseBody
    @Override
    public Map<String, ?> introspect(@RequestParam("token") String token) {
        // return data
    }
}

现在的问题是,在不考虑基本授权的情况下,正在提供对此端点的请求。所以我在配置中添加了这一行:

   @Override
   public void configure(HttpSecurity http) throws Exception {
        http
       .authorizeRequests()
       .antMatchers("/oauth/introspect").access("isAuthenticated()");

   }

现在Spring的安全性开始了,但是它并没有像对/oauth/check_token一样处理这个请求,而且我的意思是它不会自动查找表oauth_client_details,就像它对其他的一样与oauth相关的请求。因此,我得到401 http错误代码。

我想我在这里错过了一些东西告诉Spring这是oauth2请求,以便它考虑客户端ID /秘密并自动验证它。任何提示都将不胜感激。

我的配置:

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorisationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private MySecuritySettings securitySetting;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                //TODO I'd rather not to override Spring's endpoint URL but had issues with authentication. 
            .pathMapping("/oauth/check_token", "/oauth/introspect").tokenStore(this.tokenStore())
            .authenticationManager(authenticationManager)
            .tokenServices(tokenServices())
            .accessTokenConverter(tokenConverter())
            .requestValidator(createOAuth2RequestValidator());

    }


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(myClientDetailsService());
    }

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

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public MyClientDetailsService myClientDetailsService(){
        MyClientDetailsService myClientDetailsService = new MyClientDetailsService(dataSource);
        myClientDetailsService.setPasswordEncoder(passwordEncoder());
        return myClientDetailsService;
    }

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


    @Bean
    public JwtAccessTokenConverter tokenConverter() {
        final JwtAccessTokenConverter jwtAccessTokenConverter = new CompJwtAccessTokenConverter();
        DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
        defaultAccessTokenConverter.setUserTokenConverter(new CompPrincipalExtractor());
        jwtAccessTokenConverter.setAccessTokenConverter(defaultAccessTokenConverter);

        KeyPair keyPair = new KeyStoreKeyFactory(
                new ClassPathResource(securitySetting.getKeystoreFileName()),
                securitySetting.getStorepass().toCharArray())
                .getKeyPair(securitySetting.getKeyAlias(),
                        securitySetting.getKeypass().toCharArray());
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        tokenServices.setSupportRefreshToken(securitySetting.isRefreshAccessToken());
        tokenServices.setReuseRefreshToken(securitySetting.isReuseRefreshToken());
        tokenServices.setTokenEnhancer(tokenConverter());
        tokenServices.setAccessTokenValiditySeconds(securitySetting.getAccessTokenValiditySeconds());
        return tokenServices;
    }

    @Bean
    @Primary
    public OAuth2RequestValidator createOAuth2RequestValidator() {
        return new ExpressionBasedOAuth2RequestValidator();
    }

}

和此:

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_ID = "auth_serv";

    @Autowired
    TokenStore tokenStore;

    @Autowired
    MySecuritySettings mySecuritySettings;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                .resourceId(RESOURCE_ID)
                .tokenStore(tokenStore);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/oauth/introspect").access("isAuthenticated()")
                .and()
                .authorizeRequests()
                .antMatchers("/api/**/*").access("#oauth2.hasScope('" + mySecuritySettings.getAuthserverScopenameAllAccess() + "')");
    }


}

0 个答案:

没有答案