【问题标题】:Unable to generate custom error message using RestControllerAdvice for authentication failure无法使用 RestControllerAdvice 为身份验证失败生成自定义错误消息
【发布时间】:2019-04-10 20:14:26
【问题描述】:

我无法使用 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 时,服务器抛出异常而不是消息。这个问题的最佳解决方案是什么。

【问题讨论】:

    标签: java authentication exception oauth-2.0 spring-restcontroller


    【解决方案1】:

    试试这样的,

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

    这将在第一次命中时,尝试使用 OAuth 进行授权,如果失败,则会抛出身份验证失败消息。

    【讨论】:

    • ApiOperation 来自 swagger annotation liberary 有什么办法可以在不使用这个库的情况下解决。
    猜你喜欢
    • 2016-01-20
    • 2015-09-09
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    相关资源
    最近更新 更多