brief introduction
Previously, the default authentication process of spring security was used to process user-defined data and password encryption, but in the actual development, it must be to use the page developed by itself, the business processing of login success and failure, etc.
The personalization configuration is completed in the browser security config of the spring security browser project.
Custom login page
Create login page
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Standard landing page</title> </head> <body> <h2>Standard landing page</h2> <h3>Form login</h3> <form action="/authentication/form" method="post"> <table> <tr> <td>User name:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password"></td> </tr> <tr> <td colspan="2"> <button type="submit">Sign in</button> </td> </tr> </table> </form> </body> </html>
Note the path here: acrion="/authentication/form"; the path is custom
The UsernamePasswordAuthenticationFilter, by default, processes login requests from the / login path. The following configuration solves this problem
public UsernamePasswordAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); }
Override the configure method in the BrowserSecurityConfig class
@Override protected void configure(HttpSecurity http) throws Exception { //To configure }
package com.spring.security; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { //To configure http .formLogin() .loginPage("/signIn.html")//Login page path // Process login request path .loginProcessingUrl("/authentication/form") .and() .authorizeRequests() // Authorized configuration //Path without authentication .antMatchers("/signIn.html").permitAll() .anyRequest() // All requests .authenticated() // All need certification .and().csrf().disable(); } }
Start project test: http://127.0.0.1:8080/hello
Handling different types of requests
What we are doing is that there may be multiple login pages for a reusable framework. Now we can solve this problem
Create a custom Controller in the spring security browser project
package com.spring.security; import com.spring.security.support.SimpleResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RestController public class BrowserSecurityController { // Encapsulates the tool class that causes the jump request, and gets it from the session private RequestCache requestCache = new HttpSessionRequestCache(); // spring's tool class: encapsulates all jump behavior policy classes private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); /** * Jump here when identity authentication is required * * @param request * @param response * @return * @throws IOException */ @RequestMapping("/authentication/require") @ResponseStatus(code = HttpStatus.UNAUTHORIZED) public SimpleResponse requirAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { SavedRequest savedRequest = requestCache.getRequest(request, response); // If there is a request to initiate authentication // Should spring store information somewhere before jumping? if (savedRequest != null) { String targetUrl = savedRequest.getRedirectUrl(); System.out.println("Request to trigger jump:" + targetUrl); // If html request, go to login page if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) { redirectStrategy.sendRedirect(request, response, "Fill in the page to jump here without writing, etc. read from the configuration file"); } } // Otherwise, the json string to be authenticated will be returned return new SimpleResponse("Access to services requires authentication!"); } }
Create return value class in spring security browser project
package com.spring.security.support; import lombok.Data; @Data public class SimpleResponse { private Object content; public SimpleResponse(Object content) { this.content = content; } }
Solve the user-defined jump login page, read yml
Modify the spring security demo project application.yml
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1/auto_test?useUnicode=yes&characterEncoding=UTF-8&useSSL=false username: root password: 123456 hk: security: browser: loginPage: /demoLogin.html #Login page
As for the encapsulation of system configuration, the outermost encapsulation of security properties includes browserproperties, validatecodeproperties, oauth2properties;
Create a new SecurityProperties class in the spring security core project:
package com.spring.security.properties; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** * Security attribute */ @Data @ConfigurationProperties(prefix = "hk.security") public class SecurityProperties { private BrowserProperties browser = new BrowserProperties(); }
Same as BrowserProperties class
package com.spring.security.properties; import lombok.Data; /** * Browser properties */ @Data public class BrowserProperties { /** * Login page default login page signIn.html */ private String loginPage = "/signIn.html"; }
For the above configuration to take effect, you need to add a SecurityCoreConfig class
New in core project:
package com.spring.security.config; import com.spring.security.properties.SecurityProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * Security core configuration * SecurityProperties Take effect */ @Configuration @EnableConfigurationProperties(SecurityProperties.class) public class SecurityCoreConfig { }
Modifying BrowserSecurityController to read system configuration
package com.spring.security; import com.spring.security.properties.SecurityProperties; import com.spring.security.support.SimpleResponse; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @RestController public class BrowserSecurityController { // Encapsulates the tool class that causes the jump request, and gets it from the session private RequestCache requestCache = new HttpSessionRequestCache(); // spring's tool class: encapsulates all jump behavior policy classes private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Autowired private SecurityProperties securityProperties; /** * Jump here when identity authentication is required * * @param request * @param response * @return * @throws IOException */ @RequestMapping("/authentication/require") @ResponseStatus(code = HttpStatus.UNAUTHORIZED) public SimpleResponse requirAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { SavedRequest savedRequest = requestCache.getRequest(request, response); // If there is a request to initiate authentication // Should spring store information somewhere before jumping? if (savedRequest != null) { String targetUrl = savedRequest.getRedirectUrl(); System.out.println("Request to trigger jump:" + targetUrl); // If html request, go to login page if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) { redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginPage()); } } // Otherwise, the json string to be authenticated will be returned return new SimpleResponse("Access to services requires authentication!"); } }
Now the system configuration login page of demo project is: demoLogin.html
To create a new demoLogin.html page for a demo project:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>demo Login page</title> </head> <body> <h2>demo Login page</h2> </body> </html>
Modifying BrowserSecurityConfig class does not block login page
package com.spring.security; import com.spring.security.properties.SecurityProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SecurityProperties securityProperties; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { //To configure http .formLogin() .loginPage("/authentication/require")//Login page path // Process login request path .loginProcessingUrl("/authentication/form") .and() .authorizeRequests() // Authorized configuration //Path without authentication .antMatchers("/authentication/require","/signIn.html",securityProperties.getBrowser().getLoginPage()).permitAll() .anyRequest() // All requests .authenticated() // All need certification .and().csrf().disable(); } }
Launch project access: http://127.0.0.1:8080/hello
Visit: http://127.0.0.1:8080/index.html
Comment out the system configuration:
#hk: # security: # browser: # loginPage: /demoLogin.html #Login page
Restart project access: http://127.0.0.1:8080/index.html