Spring Security forms authentication

        In the previous article, we initially introduced Spring Security and used its default HTTP basic authentication to protect URL resources. In this article, we use form authentication to protect URL resources.

1. Default form authentication:

        First, create a new configuration package to store common configurations; then create a new WebSecurityConfig class to inherit WebSecurityConfigurerAdapter , as shown below:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

}

        After  adding the @EnableWebSecurity annotation to the WebSecurityConfig class , it will be automatically discovered and registered  by Spring (click the @EnableWebSecurity annotation to see that the @Configuration annotation already exists, so there is no need to add it here).

        We then look at  the definition of the configure(HttpSecurity http) method of the WebSecurityConfigurerAdapter class . As follows:

protected void configure(HttpSecurity http) throws Exception {
		logger.debug("Using default configure(HttpSecurity). If subclassed this 
			will potentially override subclass configure(HttpSecurity).");

		http
			.authorizeRequests()
				.anyRequest().authenticated()
				.and()
			.formLogin().and()
			.httpBasic();
	}

        You can see that  WebSecurityConfigurerAdapter has declared some security features by default:

                a. Verify all user requests.

                b. Allow users to authenticate using form login ( Spring Security provides a simple form login page).

                c. Allow users to use HTTP basic authentication.

        Now restart the service to apply the new security configuration. Predictably, the next time we visit localhost:8080 , we will be asked for form authentication. As shown below:

         In the above figure, we can find that the address we visit automatically jumps to localhost:8080/login , which is the default login page of Spring Security . You only need to enter the correct user name and password to jump back to the original access address .

2. Custom form authentication:

1. Preliminary configuration of custom form login page:

Although the automatically generated form login page can be started conveniently and quickly, most applications prefer to provide their own form login page. In this case, the configure()         method needs to be overridden, as follows:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	protected void configure(HttpSecurity http) throws Exception{
		http.authorizeRequests()
			.anyRequest().authenticated()
			.and()	
		.formLogin().
			loginPage("/myLogin.html")
			// 使登录页不设限访问
			.permitAll()
			.and().
		csrf().disable();
	}
}

2. Know HttpSecurity:

        HttpSecurity actually corresponds to the tags in the xml file in the Spring Security namespace configuration method . Allows us to configure security policies for specific http requests.

        In the xml file, it is commonplace to declare a large number of configurations; but in the Java configuration, according to the traditional way, we need to call it like this, as follows:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	protected void configure(HttpSecurity http) throws Exception{
		ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry 
			urlRegistry=http.authorizeRequests();

		ExpressionUrlAuthorizationConfigurer.AuthorizedUrl authorizedUrl =
			(ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)urlRegistry
				.anyRequest();
		authorizedUrl.authenticated();
		// more
		
		FormLoginConfigurer<HttpSecurity> formLoginConfigurer = 
			http.formLogin();
		formLoginConfigurer.loginPage("/myLogin.html");
		formLoginConfigurer.permitAll();
		// more
	}
}

        You can imagine how cumbersome and painful this is. HttpSecurity is first designed as a chain call . After each method is executed, an expected context will be returned to facilitate continuous calls. We don't need to care about the details of what each method returns, how to proceed to the next configuration, and so on.

        HttpSecurity provides many configuration-related methods, corresponding to the subtag <http> in the namespace configuration . For example, authorizeRequests() , formLogin() , httpBasic() and  csrf() correspond to <intercept-url> , <form-login> , <http-basic> and <csrf> tags respectively . After calling these methods, the context will return to HttpSecurity unless the and() method is used to end the current tag , otherwise the context of the chain call will automatically enter the corresponding tag field .

        The authorizeRequests() method actually returns a URL interception register, we can call anyRequest() , antMatchers() and  regexMatchers() methods provided by it to match the URL of the system and specify a security policy for it.

        The formLogin() and  httpBasic() methods both declare the form authentication methods provided by Spring Security , and return the corresponding configurators respectively. Among them, formLogin.loginPage("/myLogin.html") specifies a custom login page as  /myLogin.html , and at the same time, Spring Security will register a POST route with /myLogin.html to receive login requests.

        The csrf() method is a cross-site request forgery protection function provided by  Spring Security . When we inherit the WebSecurityConfigurerAdapter , the csrf () method will be enabled by default . More information about the csrf() method will be discussed in the following chapters to make the testing process easier. smoothly.

After restarting the service, visit localhost:8080         here , and the page will automatically jump to localhost:8080/myLogin.html . Since /myLogin.html cannot locate the page resource, a 404 page will be displayed, as shown below:

3. Write the form login page:

        The code for the form login page  myLogin.html  looks like this:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
	<div class = "login" style="width:300px;height:300px">
		<h2>Acced Form</h2>
		<div class ="login-top"></div>
		<h1>LOGIN FORM</h1>
		<form action="myLogin.html" method="post">
			<input type="text" name="username" placeholder="username"/> 
			<input type="password" name="password" placeholder="password"/> 
			<div class="forgot" style="margin-top:20px;">
				<a href="#">forgot Password</a>
				<input type="submit" value="login">
			</div>
		</form>
		<div class="login-bottom">
			<h3>New User &nbsp;<a href ="">Register</a>&nbsp;&nbsp;</h3>
		</div>
	</div>
</body>
</html>

        In the form login page, there is only one form, the user name and password are username and password respectively , and it is submitted to /myLogin.html in the form of POST .

        We place this file under resources/static/ . Restart the service, visit localhost:8080 again , and you can see the customized form login page, as follows:

         After entering the correct user name and password, click the login button to jump successfully.

4. Other form configuration items:

        After customizing the form login page, the URL for processing the login request will change accordingly. How to customize the URL ? Very simple, Spring Security provides corresponding support in form customization, the code is as follows:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	protected void configure(HttpSecurity http) throws Exception{
		http.authorizeRequests()
			.anyRequest().authenticated()
			.and()
		.formLogin()
			.loginPage("/myLogin.html")
			.loginProcessingUrl("/login")
			.permitAll()
			.and()
		.csrf().disable();
	}
}

        At this point, some readers may have doubts, because by convention, after a login request is sent and the authentication is successful, the page will jump back to the original access page. In some systems, it does jump back to the original access page, but 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 logging in to inform the front end whether the login is successful or not , the front end decides how to handle subsequent logic, rather than the server actively performing page jumps. This is also possible in Spring Security :

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	protected void configure(HttpSecurity http) throws Exception{
		http.authorizeRequests()
		.anyRequest().authenticated()
		.and()
		.formLogin()
		.loginPage("/myLogin.html")
		.loginProcessingUrl("/login")
		.successHandler(new AuthenticationSuccessHandler() {
			@Override
			public void onAuthenticationSuccess(HttpServletRequest arg0, 
					HttpServletResponse arg1, Authentication arg2)
							throws IOException, ServletException {
				arg1.setContentType("application/json;charset=UTF-8");
				PrintWriter out = arg1.getWriter();
				out.write("{\"error_code\":\"0\",\"message\":\"欢迎登录系统\"}");
			}
		})
		.failureHandler(new AuthenticationFailureHandler() {
			@Override
			public void onAuthenticationFailure(HttpServletRequest arg0,
					HttpServletResponse arg1, AuthenticationException arg2)
							throws IOException, ServletException {
				arg1.setContentType("application/json;charset=UTF-8");
				arg1.setStatus(401);
				PrintWriter out = arg1.getWriter();
				// 输出失败的原因
				out.write("{\"error_code\":\"401\",\"name\":\""+arg2.getCause()+"\","
						+ "\"message\":\""+arg2.getMessage()+"\"}}");
			}
		})
		.and()
		.csrf().disable();
	}
}

        The form login configuration module provides two methods, successHandler() and failureHandler() , which handle the logic of successful login and failed login respectively. Among them, the successHandler() method has an Authentication parameter, which carries information such as the current login user name and its role ; and the failureHandler() method carries an AuthenticationException exception parameter. The specific processing method needs to be customized according to the situation of the system.

        Formally, we do use Spring Security 's form authentication feature and customize the form login page. But in reality, this is far from enough. For example, in the actual system, the user name and password we use for normal login come from the database, but here they are all written in the configuration. Furthermore, we can set detailed permissions for each logged-in user, rather than a general role. These contents will be explained in the following chapters.

Guess you like

Origin blog.csdn.net/xhf852963/article/details/121920422