The opening

In the previous article we looked at how to customize the logon processing logic in Spring Security. In this article we will look at how to customize the logon processing logic after a successful login.

The body of the

Let’s review what Spring Security does for us after a successful login by default:

  • If you do not log in to the application, the login page is automatically redirected to when you directly access resources in the application.

  • When login is successful, the page is automatically redirected to the URL I requested before login.

How do I change the default behavior of Spring Security

For example, if we want to respond to a successful login with the following JSON response message to the front end.

{"code":200."message":"Operation successful"."data":"Login successful"}
Copy the code

Step 1

Start by copying the project project spring-security-02 from the previous section and rename it to Spring-security-03.

Maven dependencies do not need to change, as shown below:

    <dependencies>
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
	
        <dependency>
            <groupId>org.springframework.boot</groupId>                           <artifactId>spring-boot-starter-web</artifactId> 
	</dependency>

    </dependencies>
Copy the code

Step 2

The processing of custom login after a successful class GoAuthenticationFailureHandler GoAuthenticationSuccessHandler and deal with the logon failure after class

/** * Custom login success processing class */

public class GoAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

	@Autowired
	private ObjectMapper objectMapper;
    
    / * * * {" code ": 200, the" message ":" successful ", "data", "login succeeds"} *@paramrequest
	  * @paramresponse
	  * @param authentication
	  * @throws IOException
	  * @throws ServletException
	  */
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
					throws IOException, ServletException {
		response.setHeader("Content-Type"."application/json; charset=utf-8");
		response.getWriter().print(objectMapper.writeValueAsString(CommonResult.success("Login successful"))); response.getWriter().flush(); }}Copy the code
package com.example.demo.config.handler;

import com.example.demo.common.CommonResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/** * Login failure handling class */
@Component
public class GoAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Autowired
    private ObjectMapper objectMapper;

    / * * * {" code ": 500, the" message ":" logon failure: Bad credentials ", "data" : null} *@param request
     * @param response
     * @param exception
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setHeader("Content-Type"."application/json; charset=utf-8");
        response.getWriter().print(objectMapper.writeValueAsString(CommonResult.failed("Login failed:"+ exception.getMessage()))); response.getWriter().flush(); }}Copy the code

Step 3

In the WebSecurityConfig configuration class, inject the above custom processing class:

@Autowired
private GoAuthenticationSuccessHandler successHandler;

@Autowired
private GoAuthenticationFailureHandler failureHandler;
Copy the code

Step 4

To the protected void configure(HttpSecurity HTTP) method, add the following code:

// These are the original http.formLogin().loginPage("/loginPage.html")// custom login page.loginProcessingURL ("/form/login")// Custom login action, SuccessHandler (successHandler); failureHandler(failureHandler); // Custom login failure handling classCopy the code

summary

As you can see from the code above, two new configurations have been added, injecting a handler in each of the successHandler and failureHandler methods.

We focus on the next GoAuthenticationSuccessHandler processing class, by the method of rewriting AuthenticationSuccessHandler responded to a json to the front.

The failureHandler processes the login failure. In this case, we also respond to the login failure message to the front-end.

The response results can be customized according to actual requirements.

extension

In the past, if the user does not log in to access our application resources directly, it will automatically jump to the login page. If the user logs in successfully and accesses the URL without permission, it will give us a message in English, which roughly means that the user has no permission.

These are also customizable. For example, if we do not log in, the message “user is not logged in” is displayed on the client; if we do not have permission, the message “User is not authorized” is displayed on the client.

The implementation steps are as follows:

Step 1

Define two processing class GoAuthenticationEntryPoint and GoAccessDeniedHandler

`

/ * * * the custom not login or token failure handling class * / @ Component public class GoAuthenticationEntryPoint implements AuthenticationEntryPoint { @Autowired private ObjectMapper objectMapper; @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json"); response.getWriter().println(objectMapper.writeValueAsString(CommonResult.unauthorized(authException.getMessage()))); response.getWriter().flush(); @component public class implements AccessDeniedHandler {@autoWired: implements AccessDeniedHandler private ObjectMapper objectMapper; /** * @param request * @param response * @param e * @throws IOException * @throws ServletException * * @return } */ @override public void handle(HttpServletRequest Request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { response.setHeader("Content-Type", "application/json; charset=utf-8"); response.getWriter().print(objectMapper.writeValueAsString(CommonResult.forbidden(e.getMessage()))); response.getWriter().flush(); }}Copy the code

`

Step 2

Inject the two custom processing classes into the WebSecurityConfig class

	@Autowired
    private GoAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private GoAuthenticationEntryPoint entryPoint;
Copy the code

Step 3

Open the WebSecurityConfig configuration class and append the following code to the configure method:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Omit some code here
        http.exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler)// The user does not have access to the handler
            .authenticationEntryPoint(entryPoint);// The user is not logged in to the processor
    }
Copy the code

conclusion

Above, we have defined four processing classes, which are applied to the following four situations:

  1. When we log in successfully.
  2. When we failed to log in.
  3. When we access resources without logging in.
  4. When we access resources that do not have permissions.

We can optionally define these processing classes according to the actual situation, and define the processing logic according to the specific requirements. Refer to the source code in this article for detailed code.