Customize form authentication and configuration
# 1. Custom form
-
Configure the core code segment of user defined form authentication
http.formLogin() .loginPage("...") .loginProcessingUrl("...") ...;
Copied! -
Prepare a custom login page (which can be a pure html page)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Landing page</title> </head> <body> <form action="/login.do" method="post"> <p><input name="username" value="tommy" placeholder="username"></p> <p><input name="password" value="123" placeholder="password"></p> <p><button type="submit">Sign in</button></p> </form> </body> </html>
Copied! -
Configuration code in the SpringSecurityConfig class
@Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/sign-in.html") .loginProcessingUrl("/login.do") .permitAll(); // 1 this configuration is very important and is easy for novices to forget. Release access to sign-in.html http.authorizeRequests() .anyRequest() .authenticated(); // 2 http.csrf().disable();// 3 }
Copied!
The configuration of custom form authentication is very similar to that of Spring Security. The difference is that it clearly indicates the login page and the login form on the login page action .
However, there are still a few small details to be clarified:
-
In the form validation provided with Spring Security, we do not need to specify . permitAll, but it is required in custom form validation. Indicates that the page and login request are anonymous and accessible (otherwise, it doesn't make sense logically).
-
The name of the login page is not required to be sign-in.html, which can be customized.
-
.loginPage In addition to a static page (for example, / sign in. HTML), the parameter of the method can be a general URI of a non static page (for example, / login page. Do).
Spring Security will redirect to this URI to trigger the execution of the Controller. The return value of the Controller will determine which login page to display.
-
The form submission method on the landing page must be post Way.
-
.loginProcessingUrl It doesn't matter what the parameter value of the method is, but it should be the same as that on the login page (sign in. HTML) < form action="..."> The values are consistent.
-
If the action attribute value of the form of the login page is / Login, so . loginProcessingUrl() It can be omitted because its default value is / login .
If the value of your @ RequestMapping is / Login. In this case, Spring MVC will ignore the suffix by default. Therefore, the form action="/login.do",action="/login.action",action="/login.xxx" and action="/login" Equivalent.
Concatenation of chained calls of code configuration:
http.formLogin() .loginPage("/sign-in.html") .loginProcessingUrl("/login.do") .permitAll(); http.authorizeRequests() .anyRequest().authenticated(); http.csrf() .disable();
# 2. UsernamePasswordAuthenticationFilter in the filter chain
In Spring Security, the login processing in form mode is performed by the Filter chain UsernamePasswordAuthenticationFilter That is, your login request will be recognized and processed when it "goes to" usernamepasswordauthenticationfilter in the Filter chain of Spring Security.
UsernamePasswordAuthenticationFilter will obtain the user name and password from the request, match them with the standard answer provided by UserDetailsService, and finally give the answer of "passed authentication" or "failed authentication".
In this UsernamePasswordAuthenticationFilter
-
The default login request url is / login
-
The two default request parameters are username and password
-
The default request method is post
Either your customized login page must meet the above default conditions, or configure it and specify it manually.
@Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/sign-in.html") .loginProcessingUrl("/login"); // The path relative to context path, that is, it does not contain context path // .usernameParameter("username") // .passwordParameter("password") http.authorizeRequests() .antMatchers("/sign-in.html").permitAll() .anyRequest().authenticated(); http.csrf() .disable(); // Turn off csrf function }
By default, Spring Security turns on the CSRF Token function (Cross Site Request Forgery Attack Protection). Therefore, it needs to be turned off first through configuration.
TIP
But sometimes (in fact, it's a RESTful API), what you need is not page Jump, but the data returned by the server in JSON format, including login success or failure information. In this case, other schemes need to be used (see subsequent contents).
# 3. After successful certification
# 3.1 default behavior
There are two jump pages and jump paths after successful login:
-
If the user directly requests the login page, after successful login, it will jump to the root path (/) of the current application by default.
-
If a user accesses a restricted page / request and is transferred to the login page, after successful login, it will jump to the originally restricted page / request by default.
Of course, the above is the "default". You can forcibly specify through configuration. In any case, after successful login, you will jump to the xxx page.
// Login page configuration http.formLogin() .defaultSuccessUrl("/success.jsp"); // .defaultSuccessUrl("/success.jsp", true);
adopt . defaultSuccessUrl() You can specify the successful jump page in case 1 above. If you add an additional parameter true, in the second case, you will be forced to jump to this specific page after successful login.
Similarly, by . failureForwardUrl() You can specify the error page to jump to when login fails.
# 3.2 JSON returned after successful login
In some systems where the front and back ends are completely separated and all interactions are completed only by JSON, a piece of JSON data is generally returned when the login is successful to inform the front end whether the login is successful or not.
Here, you can . successHandler Methods and . failureHandler Method specifies the processing logic after "authentication passed" and "authentication failed".
http.formLogin() .loginPage("/sign-in.html") .loginProcessingUrl("/login.do") .successHandler(new SimpleAuthenticationSuccessHandler()) .failureHandler(new SimpleAuthenticationFailureHandler()) .permitAll();
above SimpleAuthenticationSuccessHandler and SimpleAuthenticationFailureHandler Classes are AuthenticationSuccessHandler and AuthenticationFailureHandler Implementation classes of interfaces, which are responsible for implementing specific reply logic:
class SimpleAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess( HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException { // The authentication object carries the current login user name and other related information // User user = (User) authentication.getPrincipal(); resp.setContentType("application/json;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.write("JSON Format string"); } } class SimpleAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure( HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException { // The e object carries the error reason of authentication resp.setContentType("application/json;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.write("JSON Format string"); } }
When integrating Spring Security and JWT, we will use the above AuthenticationSuccessHandler mechanism.