An article takes you to get Spring Security custom form login

One, login interface

The login page is the page displayed by the browser you see, Like this:

Insert picture description here
The login interface is where the login data is submitted, which is the value corresponding to the action attribute of the form in the login page.

In Spring Security, if we do not do any configuration, the default login page and login interface address are both /login, that is to say, the following two requests will exist by default:

GET http://localhost:8080/login
POST http://localhost:8080/login

If it is a GET request, it means you want to access the login page. If it is a POST request, it means you want to submit the login data.

In the previous article, we customized the login page address in SecurityConfig, as follows:

.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()

When we configured to loginPage /login.htmlafter this configuration literally, it is to set the address as the login page /login.html.

In fact, it also has a hidden operation, the interface address is also set to sign in /login.htmlthe. In other words, the new login page and login interface address are both /login.html, and now there are two requests as follows:

GET http://localhost:8080/login.html
POST http://localhost:8080/login.html

The first GET request is used to obtain the login page, and the latter POST request is used to submit the login data.

Some friends are surprised? Why can't the login page and login interface be configured separately?

In fact, it can be configured separately!

In SecurityConfig, we can loginProcessingUrlspecify the login interface address method, as follows:

.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/doLogin")
.permitAll()
.and()

After this configuration, the login page address and login interface address are separated, and each is separate.

At this time, we also need to modify the action attribute in the login page to be /doLoginas follows:

<form action="/doLogin" method="post">
<!--省略-->
</form>

At this point, the startup project re-login, we found that the login can still be successful.

So why are the two configuration addresses the same by default?

We know, form in the form of configuration FormLoginConfigurer, the class inherits from AbstractAuthenticationFilterConfigurer, so when FormLoginConfigurerthe initialization time, AbstractAuthenticationFilterConfigurerwill also be initialized in the AbstractAuthenticationFilterConfigurerconstructor, we can see

protected AbstractAuthenticationFilterConfigurer() {
    
    
	setLoginPage("/login");
}

This is how the default loginPage is configured /login.

On the other hand, FormLoginConfigurerthe initialization method initmethod also calls the parent class initmethod:

public void init(H http) throws Exception {
    
    
	super.init(http);
	initDefaultLoginFilter(http);
}

In the init method of the parent class, it is called again updateAuthenticationDefaults. Let's take a look at this method:

protected final void updateAuthenticationDefaults() {
    
    
	if (loginProcessingUrl == null) {
    
    
		loginProcessingUrl(loginPage);
	}
	//省略
}

From the logic of this approach, we can see, if the user does not have to loginProcessingUrlset the value, the default will use loginPageas loginProcessingUrl.

And if you have configured loginPagein the configuration finished loginPageafter updateAuthenticationDefaultsmethod it will still be called at this time if there is no configuration loginProcessingUrl, use the new configuration loginPageas loginProcessingUrl.

Well, seeing this, I believe my friends will understand why the login interface and the login page address at the beginning are the same

Two, login parameters

After talking about the login interface, let's talk about the login parameters.

In the previous article, the parameters in our login form are username and password. Note that this cannot be changed by default:

<form action="/login.html" method="post">
    <input type="text" name="username" id="name">
    <input type="password" name="password" id="pass">
    <button type="submit">
      <span>登录</span>
    </button>
</form>

So why is it so?

Or return to FormLoginConfigurerclass, in its constructor, we can see there are two ways to configure a user name and password:

public FormLoginConfigurer() {
    
    
	super(new UsernamePasswordAuthenticationFilter(), null);
	usernameParameter("username");
	passwordParameter("password");
}

Here, the configuration of first super call parent class, passing the UsernamePasswordAuthenticationFilterinstance that will be assigned to a parent class authFilterattributes.

The next usernameParametermethod is as follows:

public FormLoginConfigurer<H> usernameParameter(String usernameParameter) {
    
    
	getAuthenticationFilter().setUsernameParameter(usernameParameter);
	returnthis;
}

getAuthenticationFilterActually the parent class method, this method returns the authFilterproperty, which is the beginning of a set of UsernamePasswordAuthenticationFilterexamples, then call the instance setUsernameParametermethod to set the parameters of the logged-in user name:

public void setUsernameParameter(String usernameParameter) {
    
    
	this.usernameParameter = usernameParameter;
}

What is the use of the settings here? When the login request from the browser to the server, we need to request HttpServletRequesttaken out of the user's login user name and login password, how to take it? Or in the UsernamePasswordAuthenticationFilterclass, the following two methods:

protected String obtainPassword(HttpServletRequest request) {
    
    
	return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
    
    
	return request.getParameter(usernameParameter);
}

You can see, this time, it uses the default configuration usernameand passwordup.

Of course, we can also configure these two parameters by ourselves, as follows:

.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/doLogin")
.usernameParameter("name")
.passwordParameter("passwd")
.permitAll()
.and()

After the configuration is complete, also modify the front-end page:

<form action="/doLogin" method="post">
    <div class="input">
        <label for="name">用户名</label>
        <input type="text" name="name" id="name">
        <span class="spin"></span>
    </div>
    <div class="input">
        <label for="pass">密码</label>
        <input type="password" name="passwd" id="pass">
        <span class="spin"></span>
    </div>
    <div class="button login">
        <button type="submit">
            <span>登录</span>
            <i class="fa fa-check"></i>
        </button>
    </div>
</form>

Pay attention to modify the name attribute value of input and the correspondence of the server.

After the configuration is complete, restart the login test.

Three, login callback

After the login is successful, we have to deal with the situation according to the situation. Generally speaking, it is nothing more than two situations:

Front-end and back-end separate
login

The two cases are handled differently. In this article, let’s first look at the second type of login without distinction between front and back ends. I will talk about the login callbacks with separate front and back ends in the next article.

1. Successful login callback

In Spring Security, there are two methods related to successful login redirect URL:

defaultSuccessUrl
successForwardUrl

There is no difference between the two at first glance, but they actually hide the universe.

First, we at configuration time, defaultSuccessUrland successForwardUrlonly need to configure a specific configuration which is depends on your needs, two differences are as follows:

(1) defaultSuccessUrlthere is an overloaded method, we start with a parameter of the defaultSuccessUrlmethod. If we defaultSuccessUrlspecify a login page for the successful jump /index, then two cases, if you are entered directly in the browser sign-in address, after a successful login, jump directly to /index, if you are entered in a browser the other addresses, for example http://localhost:8080/hello, because the results are not logged in, and redirected to the login page, after the login is successful this time, they will not come /index, but came to /hellothe page.
(2) defaultSuccessUrlthere is an overloaded method, the second parameter if the default is not set false, that is, we the above case, if you manually set the second parameter is true, the defaultSuccessUrleffectiveness and successForwardUrlconsistency.
(3) successForwardUrlindicate no matter where you are from, log all jump to successForwardUrlthe specified address. For example, successForwardUrlspecified address /index, you enter in the browser address bar http://localhost:8080/hello, because the results are not logged in, redirect to the login page when you log in successfully, the server will jump to the /indexpage; or you directly in your browser and enter login The page address will also come after successful login /index.

.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/doLogin")
.usernameParameter("name")
.passwordParameter("passwd")
.defaultSuccessUrl("/index")
.successForwardUrl("/index")
.permitAll()
.and()

Note: In actual operation, only one of defaultSuccessUrl and successForwardUrl needs to be configured

2. Login failure callback

Similar to successful login, there are two methods for failed login:

failureForwardUrl
failureUrl

You can also set one of these two methods when setting.
failureForwardUrl is a server-side redirect after login failure, and failureUrl is a redirect after login failure.

Four, log out

The default interface for logout is /logout, we can also configure it.

.and()
.logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout","POST"))
.logoutSuccessUrl("/index")
.deleteCookies()
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll()
.and()

Let me talk about the logout configuration:

(1) The URL is the default cancellation /logoutis a GET request, we can logoutUrlmodify the default logout URL method.
(2) The logoutRequestMatchermethod can not only modify the logout URL, but also modify the request method. In the actual project, this method and logoutUrl can be arbitrarily set.
(3) logoutSuccessUrlIndicates the page to jump to after the logout is successful.
(4) deleteCookiesUsed to clear cookies.
(5) clearAuthenticationand invalidateHttpSessionrepresent the clear failure of the authentication information and the HttpSession, you can not configure a default, the default is cleared.

Guess you like

Origin blog.csdn.net/nanhuaibeian/article/details/108583418