Oauth2 - получение неверной учетной записи клиента в ClientCredentialsTokenEndpointFilter - PullRequest
0 голосов
/ 28 сентября 2018

Я получаю сообщение об ошибке «Недопустимые учетные данные клиента» при вызове конечной точки oauth2 http://localhost:8080/oauth/token.

Я переопределил поведение по умолчанию при проверке учетных данных клиента с помощью MyClientCredentialsTokenEndpointFilter.На самом деле я просто хочу использовать учетные данные клиента, чтобы узнать источник запроса.Если клиент не отправляет его, я хотел бы сравнить его с моими учетными данными по умолчанию и разрешить продолжить.Я знаю, что это не рекомендуется, но у меня есть такое требование.Для этого мне нужно установить правильный менеджер аутентификации в MyClientCredentialsTokenEndpointFilter.В настоящее время это проверка учетных данных клиента с учетными данными пользователя, который вызывает проблему.Я прошу вас помочь, чтобы я мог создать менеджер аутентификации, используя учетные данные, хранящиеся в ClientDetailsServiceConfigurer, а затем установить его в свой пользовательский фильтр.

Вот моя конфигурация сервера авторизации.Я настроил учетные данные клиента здесь.Здесь, в 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;
    }
}

Пожалуйста, дайте мне знать, как правильно зарегистрировать диспетчер аутентификации, чтобы учетные данные были проверены по учетным данным клиента.

...