Oauth2-在ClientCredentialsTokenEndpointFilter中获取无效的客户端凭据错误

时间:2018-09-28 08:14:51

标签: spring spring-security spring-security-oauth2 spring-oauth2

在调用oauth2端点http://localhost:8080/oauth/token时出现“错误的客户端凭据”错误。

我已覆盖使用MyClientCredentialsTokenEndpointFilter验证客户端凭据的默认行为。 实际上,我只想使用客户端凭据来了解请求的来源。 如果客户端没有发送它,那么我想将其与默认凭据进行比较,并允许其继续进行。我知道不推荐这样做,但是我有这样的要求。 为此,我需要在MyClientCredentialsTokenEndpointFilter中设置正确的身份验证管理器。 当前,它正在使用引起问题的用户凭据来验证客户端凭据。 我要求您提供帮助,以便我可以使用ClientDetailsS​​erviceConfigurer中存储的凭据创建身份验证管理器,然后将其设置为我的自定义过滤器。

这是我的授权服务器配置。我已经配置了客户端凭据 这里。在myClientCredentialsTokenEndpointFilterBean中,这里设置了错误的身份验证管理器对象。

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    static final String CLIEN_ID = "client";
    static final String CLIENT_SECRET = "secret";
    static final String GRANT_TYPE_PASSWORD = "password";
    static final String AUTHORIZATION_CODE = "authorization_code";
    static final String REFRESH_TOKEN = "refresh_token";
    static final String IMPLICIT = "implicit";
    static final String SCOPE_READ = "read";
    static final String SCOPE_WRITE = "write";
    static final String TRUST = "trust";
    static final int ACCESS_TOKEN_VALIDITY_SECONDS = 1*60*60;
    static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 6*60*60;

    @Autowired
    private AuthenticationManager authenticationManager;

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

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


   @Bean
    public MyClientCredentialsTokenEndpointFilter myClientCredentialsTokenEndpointFilterBean(ClientDetailsServiceConfigurer configurer) throws Exception{

        MyClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter= new MyClientCredentialsTokenEndpointFilter();
        clientCredentialsTokenEndpointFilter.setAuthenticationManager(authenticationManager);
        clientCredentialsTokenEndpointFilter.afterPropertiesSet();
        return clientCredentialsTokenEndpointFilter;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {

        configurer
                .inMemory()
                .withClient(CLIEN_ID)
                .secret(CLIENT_SECRET)
                .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT )
                .scopes(SCOPE_READ, SCOPE_WRITE, TRUST)
                .accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS).
                refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
    }

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

这是我要验证客户端凭据的过滤器实现-

public class MyClientCredentialsTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter {

    private static final String CONST_DEFAULT_CLIENT_ID = "my-client";

    private final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

    public MyClientCredentialsTokenEndpointFilter() {
        super("/token");
    }
    @Override
    public Authentication attemptAuthentication(final HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {

         HttpInputMessage inputMessage = new ServletServerHttpRequest(request);
         TokenRequestParameters params = null;
         try {
             params = (TokenRequestParameters)converter.read(TokenRequestParameters.class,  inputMessage);
         }catch(Exception e) {
             logger.error("Failed to parse parameters : " + e.getLocalizedMessage());
             throw new BadCredentialsException(e.getMessage());
         }
         String clientId = params.getClientId() != null ? params.getClientId() : CONST_DEFAULT_CLIENT_ID;

         String clientSecret = "secret";


         // If the request is already authenticated we can assume that this filter is not needed
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
         if (authentication != null && authentication.isAuthenticated()) {
             return authentication;
         }

         UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId,
                 clientSecret);
         System.out.println("authResult::111111111");
         Authentication authResult = this.getAuthenticationManager().authenticate(authRequest);
         System.out.println("authResult::"+authResult);
         SecurityContextHolder.getContext().setAuthentication(authResult);
         return authResult;

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequestWrapper reqWrapper = new CachedInputStreamHttpServletRequestWrapper((HttpServletRequest)req);
        super.doFilter(reqWrapper, res, chain);
    }

}

这是我的资源服务器配置-

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_ID = "resource_id";

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

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
                anonymous().disable()
                .authorizeRequests()
                .antMatchers("/users/**").access("hasRole('ADMIN')")
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

}

这是我的安全配置-

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource(name = "userService")
    private UserDetailsService userDetailsService;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(encoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .antMatchers("/api-docs/**").permitAll();
    }

    @Bean
    public BCryptPasswordEncoder encoder(){
        return new BCryptPasswordEncoder(4);
    }

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

请告诉我如何正确注册身份验证管理器,以便针对客户端凭据验证凭据。

0 个答案:

没有答案