Невозможно сгенерировать пользовательское сообщение об ошибке с помощью RestControllerAdvice для сбоя аутентификации

#java #authentication #exception #oauth-2.0 #spring-restcontroller

#java #аутентификация #исключение #oauth-2.0 #spring-restcontroller

Вопрос:

Я не могу сгенерировать пользовательское сообщение с помощью RestControllerAdvice для сбоя аутентификации OAuth2.

Сервер ресурсов :

 @Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{

    public ResourceServerConfiguration() {
        System.out.println("ResourceServerConfiguration : constructor");
    }

    private static final String RESOURCE_ID = "my_rest_api";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        System.out.println("ResourceServerConfiguration : configure with requested resources");
        resources.resourceId(RESOURCE_ID).stateless(false);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        System.out.println("ResourceServerConfiguration : configure with requested http request");
        http.
        anonymous().disable()
        .requestMatchers().antMatchers("/login/**")
        .and().authorizeRequests()
        .antMatchers("/login/**").access("hasRole('ADMIN')")
        .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }

}
  

Сервер авторизации :

 @Configuration
@EnableAuthorizationServer   
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter{

    public AuthorizationServerConfiguration() {
        System.out.println("Inside AuthorizationServerConfiguration");
    }

    /*class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer 
     * which provides all the necessary methods to configure an Authorization server.*/
    private static String REALM = "MY_OAUTH_REALM";

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        System.out.println("AuthorizationServerConfiguration configure for security");
        security.realm(REALM "/client");
    }

    //configures authorization using password authentication
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        System.out.println("AuthorizationServerConfiguration configure for clients");
        clients.inMemory()
        .withClient("my-trusted-client")
        .authorizedGrantTypes("password","authorization_code", "refresh_token", "implicit")
        .authorities("ROLE_CLIENT","ROLE_TRUSTED_CLIENT")
        .scopes("read","write","trust")     
        .secret("secret")
        .accessTokenValiditySeconds(120) //Access token is only valid 2 min.
        .refreshTokenValiditySeconds(600);// refresh token is valid for 10 mins.

    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        System.out.println("AuthorizationServerConfiguration configure for endpoints");
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler).authenticationManager(authenticationManager);
    }
}
  

Веб-безопасность :

 @Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    public OAuth2SecurityConfiguration() {
        System.out.println("OAuth2SecurityConfiguration : constructor");        
    }

    @Autowired
    private ClientDetailsService clientDetailsService;

    @Autowired
    private void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception{
        System.out.println("OAuth2SecurityConfiguration : Set global users");
        auth.inMemoryAuthentication()
        .withUser("abc").password("abc@123").roles("ADMIN");
        System.out.println("Auth :" auth);
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        System.out.println("OAuth2SecurityConfiguration : authenticationManagerBean");
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println("OAuth2SecurityConfiguration : path set as /oauth/token");
        http
            .sessionManagement()
            .and()
            .cors()
            .and()
            .csrf().disable()
            .anonymous().disable()
            .authorizeRequests().antMatchers("/oauth/token").permitAll()
            .and()
            .formLogin().disable()
            .httpBasic().disable()
            .logout().disable(); 
    }

    @Bean
    public TokenStore tokenStore() {
        System.out.println("OAuth2SecurityConfiguration : tokenStore");
        return new InMemoryTokenStore();
    }

    @Override
    public void configure( WebSecurity web ) throws Exception
    {
        web.ignoring().antMatchers( HttpMethod.OPTIONS, "/**" );
    }

    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
        System.out.println("OAuth2SecurityConfiguration : get user approval handler for requested tokenStore");
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }

    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        System.out.println("OAuth2SecurityConfiguration : create approval store for requested tokenStore");
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
}
  

RestControllerAdvice

 @RestControllerAdvice
public class RestErrorHandler {

    @ExceptionHandler({AuthenticationException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public ResponseEntity<String> handleAuthenticationException(AuthenticationException ex) {
        return ErrHandler.getInstance().getErrResp(ErrorMsg.AUTH_EXCEPTION.getErrCd(), ErrorMsg.AUTH_EXCEPTION.getErrMsg());
    }

    @ExceptionHandler({HttpMessageNotReadableException.class,BadCredentialsException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseEntity<String> badRequestException(HttpMessageNotReadableException  ex) {
        return ErrHandler.getInstance().getErrResp(ErrorMsg.BAD_REQ_EXCEPTION.getErrCd(), ErrorMsg.BAD_REQ_EXCEPTION.getErrMsg());
    }

}
  

При доступе к URL-адресу без аутентификации сервер выдает исключение, а не сообщение. Каково наилучшее решение этой проблемы.

Ответ №1:

Попробуйте что-то вроде этого,

  @ApiOperation(authorizations = {
      @Authorization(value = "oauth") }, value = "Method does some function", response = String.class)
  

При первом попадании попробуйте авторизоваться с помощью OAuth, в случае сбоя это выдаст сообщение об ошибке аутентификации.

Комментарии:

1. ApiOperation из библиотеки аннотаций swagger Есть ли какой-либо способ, которым я могу работать без использования этой библиотеки.