This article complete code download click

A preface.

If you know me or have seen my previous series of articles, you should know that I wrote these articles for the purpose of creating youlai-Mall, to provide a stepping stone for those who really want to improve themselves or are confused. The project really starts from scratch (as evidenced by previous articles), and uses the current mainstream development mode (microservice + front-end separation), the latest mainstream technology stack (Spring Boot+ Spring Cloud +Spring Cloud Alibaba + Vue), The most popular unified security authentication authorization (OAuth2+JWT), good joke finished we don’t take it seriously, in short, interested partners welcome to join ~

Next, let’s talk about the reason for this article. Before, I did not think of the combination of OAuth2+JWT applied to the project so much attention. During the period, there have been children asking how to customize Spring Security OAuth2 exception handling, JWT how to renew, JWT exit scenarios how to fail and other problems. So recently I have some time to complete this set of unified authentication and authorization. This article will focus on how to customize Spring Security OAuth2 exception handling.

Links to previous articles:

The back-end

  1. Spring Cloud of actual combat | first article: Windows setup Nacos services
  2. The second Spring Cloud of actual combat | : Spring Cloud integration Nacos registry
  3. Spring Cloud of actual combat | article 3: the Spring Cloud integration Nacos configuration center
  4. Spring Cloud of actual combat | article 4: Spring Cloud integration Gateway API Gateway
  5. Spring Cloud of actual combat | article 5: Spring Cloud integration OpenFeign between micro service calls
  6. Spring Cloud of actual combat | article 6: the Spring Cloud + Spring Security Gateway OAuth2 + JWT micro service unified certificate authority
  7. Spring Cloud of actual combat | the seven articles: Spring Cloud + Spring Security Gateway OAuth2 integrated unified certificate authority platform to realize the logout disable JWT scheme
  8. Spring Cloud of actual combat | the eight: Spring Cloud + Spring Security OAuth2 + Vue no refresh perception to realize the separation mode before and after JWT renewed
  9. Spring Cloud of actual combat | the nine article: Spring Security OAuth2 authentication server unified authentication custom exception handling

Management of the front

  1. Vue – element – admin combat | first article: remove the mock access background, building a youlai – mall to mall before and after the separation management platform
  2. Vue – element – the second admin combat | : minimal change access backend implementation according to the dynamic loading menu

Wechat applets

  1. Vue + uniapp mall real | first article: 【 】 has to store WeChat small programs to rapidly develop access Spring Cloud OAuth2 authentication center to complete the authorization to log in

Two. Custom exception implementation code

Directly need answers to this section, add and modify three files can be, anomaly analysis, click download complete project code

1. Add AuthExceptionHandler to the YouLai-Auth authentication server module

package com.youlai.auth.exception;

import com.youlai.common.core.result.Result;
import com.youlai.common.core.result.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
@Slf4j
public class AuthExceptionHandler {

    /** * The username and password are incorrect **@param e
     * @return* /
    @ExceptionHandler(InvalidGrantException.class)
    public Result handleInvalidGrantException(InvalidGrantException e) {
        return Result.custom(ResultCode.USERNAME_OR_PASSWORD_ERROR);
    }

    /** * Account is abnormal (disabled, locked, expired) **@param e
     * @return* /
    @ExceptionHandler({InternalAuthenticationServiceException.class})
    public Result handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e) {
        returnResult.error(e.getMessage()); }}Copy the code

2. Rewrite ClientCredentialsTokenEndpointFilter achieve client custom exception handling

package com.youlai.auth.filter;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter;
import org.springframework.security.web.AuthenticationEntryPoint;

/** * Override filter to implement client-side custom exception handling */
public class CustomClientCredentialsTokenEndpointFilter extends ClientCredentialsTokenEndpointFilter {

    private AuthorizationServerSecurityConfigurer configurer;
    private AuthenticationEntryPoint authenticationEntryPoint;


    public CustomClientCredentialsTokenEndpointFilter(AuthorizationServerSecurityConfigurer configurer) {
        this.configurer = configurer;
    }

    @Override
    public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
        super.setAuthenticationEntryPoint(null);
        this.authenticationEntryPoint = authenticationEntryPoint;
    }

    @Override
    protected AuthenticationManager getAuthenticationManager(a) {
        return configurer.and().getSharedObject(AuthenticationManager.class);
    }

    @Override
    public void afterPropertiesSet(a) { setAuthenticationFailureHandler((request, response, e) -> authenticationEntryPoint.commence(request, response, e)); setAuthenticationSuccessHandler((request, response, authentication) -> { }); }}Copy the code

3. AuthorizationServerConfig authentication server configuration changes

/** * Authorization service configuration */
@Configuration
@EnableAuthorizationServer
@AllArgsConstructor
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {...@Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        /*security.allowFormAuthenticationForClients(); * /
        CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security);
        endpointFilter.afterPropertiesSet();
        endpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint());
        security.addTokenEndpointAuthenticationFilter(endpointFilter);

        security.authenticationEntryPoint(authenticationEntryPoint())
                .tokenKeyAccess("isAuthenticated()")
                .checkTokenAccess("permitAll()");
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint(a) {
        return (request, response, e) -> {
            response.setStatus(HttpStatus.HTTP_OK);
            response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.setHeader("Access-Control-Allow-Origin"."*");
            response.setHeader("Cache-Control"."no-cache"); Result result = Result.custom(ResultCode.CLIENT_AUTHENTICATION_FAILED); response.getWriter().print(JSONUtil.toJsonStr(result)); response.getWriter().flush(); }; }... }Copy the code

3. Exception processing analysis

Spring Security OAuth2 can be used as a custom exception handler for Spring Security OAuth2. ! What’s up? In fact, it can not be arbitrarily said that other people’s solution is not good. The most likely reason is that the version of Spring Security OAuth2 is inconsistent. This project uses version 2.3.4. If there are differences, I will modify this article, in short, to provide you with a solution, feasible or not FEASIBLE I do not hope that you can not waste time in me.

Spring Security OAuth2 authentication server exception

  1. The user name or password is incorrect
  2. Abnormal Account Status
  3. The client authentication is abnormal. Procedure

There are other welcome messages to add ~, the following three types of exception analysis

Before handling the exception, take a look at the exception thrown by the UserDetailsServiceImpl#loadUserByUsername method as shown below:

1. The user name or password is incorrect

  • Abnormal analysis
Org.springframework.security.oauth2.com mon. Exceptions. InvalidGrantException: user name or password errorCopy the code

Through the exception stack information positioning an exception to the final approach is to ResourceOwnerPasswordTokenGranter# getOAuth2Authentication, Exception type is InvalidGrantException, in fact, between the exception type after several conversion UsernameNotFoundException – > BadCredentialsException – > InvalidGrantException

  • Processing method

Add global exception handler capture (location identifier: AuthExceptionHandler)


/** * The user name and password are abnormal **@param e
 * @return* /
@ExceptionHandler(InvalidGrantException.class)
public Result handleInvalidGrantException(InvalidGrantException e) {
    return Result.error(ResultCode.USERNAME_OR_PASSWORD_ERROR);
}
Copy the code
  • results

The verification is successful and the custom exception format is returned

2. The account status is abnormal

  • Abnormal analysis

Select sys_user from youlai (select sys_user from youlai (select sys_user from youlai (select sys_user from youlai (select sys_user from youlai))); Eventually positioning to ProviderManager# authenticate method throws the exception, is InternalAuthenticationServiceException exception type.

  • Processing method

Add global exception handler capture (location identifier: AuthExceptionHandler)

/ * * * account exception (disabled, locking, expired) @ param e * * * @ return * / @ ExceptionHandler ({InternalAuthenticationServiceException. Class}) to the public Result handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e) { return Result.error(e.getMessage()); }Copy the code
  • results

The verification is successful and the custom exception format is returned

3. The client authentication is abnormal

  • Abnormal analysis

Both of the previous exceptions can be caught by the global exception handler, and @RestControllerAdvice can only catch Controller exceptions.

Client authentication exceptions occur on filter, at this time, before entering the DispatcherServlet request processing process, it cannot be captured by the global exception processor.

Check the location of the client authentication exception and change the client ID to the wrong one.

Then perform the Login operation, and the following error message is returned:

{"error":"invalid_client","error_description":"Bad client credentials"}
Copy the code

At first glance, this is clearly not the format we want.

So how do I catch this exception and turn it back into a custom data format? Obviously the global exception handler cannot be implemented, so you have to think differently.

Client authentication is accomplished by ClientCredentialsTokenEndpointFilter first, including the rear add failure treatment method, finally the exception to this so-called OAuth2AuthenticationEntryPoint authentication entry processing.

Authentication entrance OAuth2AuthenticationEntryPoint # # commence method to the superclass AbstractOAuth2SecurityExceptionHandler doHandle method.

Finally exception frames on the AbstractOAuth2SecurityExceptionHandler # doHandle method, the diagram below:

The enclosing enhanceResponse is call OAuth2AuthenticationEntryPoint # enhanceResponse method for response results data.

  • Processing method

We learned that the above client authentication failure is exception filters ClientCredentialsTokenEndpointFilter to OAuth2AuthenticationEntryPoint get response results, In this case we can rewrite ClientCredentialsTokenEndpointFilter then use custom AuthenticationEntryPoint replace the native OAuth2AuthenticationEntryPoint, We get the exception data we want in the custom AuthenticationEntryPoint processing.

Customize AuthenticationEntryPoint to set the exception response data format

Rewrite AuthenticationEntryPoint ClientCredentialsTokenEndpointFilter replacement

Authentication server configuration Add a custom filter

  • results

The verification is successful and the custom exception format is returned

4. To summarize

At this point, the authentication server of the custom exception handling has been processed, the resource server exception handling instructions in this article the Spring Cloud of actual combat | article 6: Spring Cloud Gateway+Spring Security OAuth2+JWT realize unified authentication and authorization for micro services, which declares that the unified authentication and authorization module of YouLai-Mall has basically reached a perfect standard. Later continue to return to the development of business functions, so feel helpful to you to pay attention to (continuous update) or give a star, grey often thank you! Most importantly, if you are really interested in this project and want to develop and learn together, please contact me as mentioned at the beginning of this article