Spring Security Log separated front and rear ends, illegal requests directly return JSON

hello everybody junior partner, the National Day has finally been done for, Song Ge also come back, starting today we continue to dry hair!

Numerous articles on hair before Spring Security, Song Ge and we talk about this security framework to use:

  1. Getting your hands with Spring Security!
  2. Spring Security log in to add a verification code
  3. SpringSecurity Login using JSON data format
  4. Spring Security in the role of inheritance
  5. Spring Security is used JWT!
  6. Spring Security combined OAuth2

Today, however, and small partners to chat with Spring Security is another problem in that request has not been approved will be redirected to the default login page in the Spring Security, but the back-end login separation of the former, this default behavior then it is very inappropriate, and today we take a look at how to achieve the main not been authenticated requests directly return JSON, instead of redirecting to the login page.

Pre-knowledge

Here on the basic usage of Spring Security I will not repeat them, if little friends do not understand, you can refer to the above six articles.

As we all know, when a custom configuration Spring Security, have several attributes:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .formLogin()
            .loginProcessingUrl("/doLogin")
            .loginPage("/login")
            //其他配置
            .permitAll()
            .and()
            .csrf().disable();
}

There are two important attributes:

  • loginProcessingUrl: This indicates that the interface address configuration logon request, for example, you are a form login, then the value of the value of the action form the form is filled here.
  • loginPage: This indicates the address of the login page, such as when you need to log in after a visit to access the resource, the system will automatically give you this by redirecting Jump to page up.

This configuration login, regardless of the back-end of the front is no problem, log on separate back-end of the front, this configuration have a problem. Let me give a simple example, such as I want to access /hellothe interface, but this interface to access later need to sign, I do not log in directly to access this interface, then the system will return to my 302, so I went to the login page, before and after end separation, my backend is generally not logged in page, it is a prompt JSON, such as this:

@GetMapping("/login")
public RespBean login() {
    return RespBean.error("尚未登录,请登录!");
}

The complete code you can refer to my micro-personnel items.

That is, when I do not have to log in directly access /hellothis interface, I see the above paragraph JSON string. Separate back-end development front, this looks good (back-end do not jump page, no matter what happens all return JSON). But the problem lies here, the default jump is a redirect, that when you visit /hellotime, the server will return to the browser 302, while there is a Location response header field, its value http://localhost:8081/login, that is, you tell the browser to access the http://localhost:8081/loginaddress bar. After the browser receives the instruction, it will go directly to the access http://localhost:8081/loginaddress, if this time is the development environment and the request is an Ajax request, it will occur across domains. Because the separation of the front and rear end development, front-end on NodeJS we usually start, and then the front end of all requests forwarded request made by NodeJS, now request directly to the server address to the browser, and the browser will go directly to visit http://localhost:8081/login, and without It does forward the request, and therefore cross-domain problem has occurred.

solution

Obviously, the above problem we can not use cross-domain ideas to solve, although this approach seems also to solve the problem, but not the best option.

If our Spring Security user has not been authenticated in time to request a data request to require authentication, in which case the user is not redirected, but directly returns a JSON, tell the user to initiate this request after authentication is required, it It will not have the above things.

Here relates to an interface in Spring Security AuthenticationEntryPoint, the interface implementation class a: LoginUrlAuthenticationEntryPoint, the class has a method commence, as follows:

/**
 * Performs the redirect (or forward) to the login form URL.
 */
public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) {
    String redirectUrl = null;
    if (useForward) {
        if (forceHttps && "http".equals(request.getScheme())) {
            redirectUrl = buildHttpsRedirectUrlForRequest(request);
        }
        if (redirectUrl == null) {
            String loginForm = determineUrlToUseForThisRequest(request, response,
                    authException);
            if (logger.isDebugEnabled()) {
                logger.debug("Server side forward to: " + loginForm);
            }
            RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);
            dispatcher.forward(request, response);
            return;
        }
    }
    else {
        redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);
    }
    redirectStrategy.sendRedirect(request, response, redirectUrl);
}

First, we can see from the comments of this method, this method is used to determine in the end is still to be redirected to forward, through the Debug tracing, we found useForward the default value is false, so the request into the redirection .

So the idea that we solve the problem is simple, direct override this method, the method returns JSON can no longer do redirection, the specific configuration is as follows:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .formLogin()
            .loginProcessingUrl("/doLogin")
            .loginPage("/login")
            //其他配置
            .permitAll()
            .and()
            .csrf().disable().exceptionHandling()
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException authException) throws IOException, ServletException {
                resp.setContentType("application/json;charset=utf-8");
                PrintWriter out = resp.getWriter();
                RespBean respBean = RespBean.error("访问失败!");
                if (authException instanceof InsufficientAuthenticationException) {
                    respBean.setMsg("请求失败,请联系管理员!");
                }
                out.write(new ObjectMapper().writeValueAsString(respBean));
                out.flush();
                out.close();
            }
        });
}

In Spring Security configuration plus custom AuthenticationEntryPointprocessing method, the method returns directly to the appropriate prompts to JSON. In this way, if the request after a user to go directly access requires authentication before they can access, it will not happen redirection, the server directly to the browser a JSON prompt after the browser receives the JSON, the Why Why .

Epilogue

Well, the next question a little redirection and small partners to share, do not know if you have read it? This is my question recently reconstructed micro personnel when encountered. Expected in November, Spring Boot version micro personnel will be upgraded to the latest version, please pay attention to small partners Oh.

Public concern number one o'clock the rain [southern], focusing on the Spring Boot + Micro service and front and rear ends of separation full stack technology, video tutorials on a regular basis to share concerns reply after Java, Java dry Song Ge receive carefully prepared for you!

Guess you like

Origin www.cnblogs.com/lenve/p/11645640.html