Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize automatic login function in Spring Security hash encryption

2025-04-11 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces you how to achieve automatic login function in Spring Security hash encryption, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Preface

In the previous two chapters, one elder brother took you to add graphic CAPTCHA verification function in Spring Security, in fact, the function of Spring Security is not only these, but also can achieve many other effects, such as automatic login, login login and so on.

Some friends will ask, why do we want to log in automatically? This requirement is actually very common, because for users, they may often need to log in and log out. If you think about it, is it annoying if users have to enter their username and password every time they log in? is the user experience very bad?

So in order to improve the user experience of the project, we can add automatic login function to the project, and of course, we should also provide users with the function of logging out. Then follow one by one to learn how to achieve these functions!

one。 Introduction to automatic login 1. Why log in automatically?

When we visit a website or app, we are generally required to sign up for an account that contains user name and password information, in which the password will be limited in length and value range. In many cases, the accounts we register on different sites may have different passwords, which makes us have to remember the user information on different sites. So the next time we log in, because we have too many passwords, we may not remember these account passwords. So after several failed login attempts, many people choose to retrieve their passwords and fall back into the cycle of how to set their passwords again.

In order to minimize the frequency of re-login and improve the user experience, we can provide an experiential function of automatic login, which will bring convenience and risk to the user at the same time.

two。 Implementation scheme of automatic login

After understanding the background and function of automatic login, how can we achieve automatic login?

First of all, we know that automatic login is a mechanism that saves the user's login information in the cookie of the user's browser and automatically verifies and establishes the login status the next time the user visits.

Therefore, based on the above principle, Spring Security provides us with two better solutions for automatic login:

Based on hash encryption algorithm mechanism: encrypt the necessary login information of users, and generate tokens to achieve automatic login, using TokenBasedRememberMeServices class to achieve.

Based on database and other persistent data storage mechanisms: generate persistent tokens to achieve automatic login, using PersistentTokenBasedRememberMeServices to achieve.

The two implementation classes I mentioned above are actually subclasses of AbstractRememberMeServices, as shown in the following figure:

Once we understand these core API, we can use these two API to implement automatic login.

two。 Automatic login based on hash encryption scheme

Let me first take you to use the first implementation scheme, that is, based on hash encryption scheme to achieve automatic login.

First of all, we still develop on the basis of the previous case, and skip the specific project creation process. Please refer to the previous chapter.

1. Configure the key of an encrypted token

First, let's create an application.yml file to add the database configuration and a key string to encrypt tokens. The value of the string can be customized.

Spring: datasource: url: jdbc:mysql://localhost:3306/db-security?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT username: root password: syc security: remember-me: key: yyg2. Configure the SecurityConfig class

As in the previous case, I'm still going to create a SecurityConfig class in which the configure (HttpSecurity http) method associates our database through JdbcTokenRepositoryImpl and turns on the "remember me" function through the rememberMe () method, as well as configuring the rememberKey we previously had in the configuration file as a hash encrypted key.

@ EnableWebSecurity (debug = true) public class SecurityConfig extends WebSecurityConfigurerAdapter {@ Value ("${spring.security.remember-me.key}") private String rememberKey; @ Autowired private UserDetailsService userDetailsService; @ Override protected void configure (HttpSecurity http) throws Exception {/ / use JdbcTokenRepositoryImpl to associate the data source JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl (); tokenRepository.setDataSource (dataSource) Http.authorizeRequests () .antMatrices ("/ admin/**") .hasRole ("ADMIN") .antMatrices ("/ user/**") .hasRole ("USER") .antMatrices ("/ app/**") .permitAll () .anyRequest () .authenticated () .and () .formLogin () .permitAll () .and () / enable the remember me feature.rememberMe () .userDetailsService (userDetailsService) / / configure hash Key .key (rememberKey) .and () .csrf () .disable () for encryption } @ Bean public PasswordEncoder passwordEncoder () {/ / do not encrypt the login password return NoOpPasswordEncoder.getInstance ();}} 3. Add test interface

In order to facilitate subsequent testing, I casually write a web interface for testing.

@ RestController@RequestMapping ("/ user") public class UserController {@ GetMapping ("hello") public String hello () {return "hello, user";} 4. Start the project test

Then we start the project for testing, of course, you do not forget to write the project entry class, I will not paste the relevant code here.

When we visit the / user/hello interface, we will redirect to the / login interface first, and we will find that there is an extra "remember me" function on the default login page.

At this point, if we open the developer debugging tool and check "remember me", and then initiate the request, we will see the cookie information of remember-me on the console, indicating that Spring Security has automatically generated the cookie of remember-me, and the remember-me parameter in the form is in the "on" state.

In other words, we use a few simple lines of code to achieve automatic login based on the hash encryption scheme.

three。 Implementation principle of hash encryption scheme

You may wonder how the hash encryption scheme enables automatic login. Don't worry, next I will analyze the implementation principle of hash encryption for you.

1. Analysis of encryption principle of cookie

As I said earlier, automatic login is actually a mechanism that saves the user's login information in the cookie of the user's browser and automatically verifies and establishes the login status the next time the user visits. Therefore, after the automatic login, the cookie information on behalf of the user will certainly be generated, but for the sake of security, the cookie will certainly not be stored in plaintext. It needs to be encrypted and decoded, of course. So next I'm going to analyze the encryption and decoding process of this cookie.

First of all, I would like to explain to you the so-called hash encryption algorithm, whose essence is to combine username, expirationTime, password and other fields, together with custom key fields, to separate each field with ":", and finally use the md5 algorithm for hashing, so that you can get an encrypted string. Spring Security stores this encrypted string in cookie as identification information that the user has logged in.

Then I will show you the makeTokenSignature () method in the TokenBasedRememberMeServices source code class, and you will see the specific encryption implementation process of the hash encryption algorithm. The source code is shown below:

2. Analysis of decoding principle of cookie

The above is encrypted using MD5, and the user will definitely need to compare the information after the next login to determine whether the user's information is consistent. Spring Security first decodes the information in the cookie and then compares it with the previously recorded login information to determine whether the user has logged in.

Spring Security uses Base64 to decode cookie in the decodeCookie () method of the AbstractRememberMeServices class, as shown in the following figure:

For the above two source code methods, we can simply extract the following two lines of code:

/ / encrypt the fields with hash hashInfo=md5Hex (username+ ":" + expirationTime + ":" password+ ":" + key) / / use base64 to decode rememberCookie=base64 (username+ ":" + expirationrime+ ":" + hashInfo)

Where expirationTime refers to the validity period of this automatic login, and key is a hash salt value specified by yourself to prevent tokens from being modified. Take advantage of the above two

After analyzing the source code, I will give you a brief summary of the generation and verification principles of cookie:

First, use the above source code to generate cookie and save it in the browser.

After the browser is closed and reopened, when the user visits the / user/hello interface, the cookie of remember-me will be brought to the server.

After the server gets the cookie, it decodes it with Base64, calculates the user name and expiration time, and then queries the user password according to the user name.

Finally, the hash value is calculated through the MD5 hash function, and the calculated hash value is compared with the hash value passed by the browser to confirm whether the token is valid.

3. Source code analysis of automatic login

After analyzing the encryption and decoding of cookie information above, I introduce the implementation process of automatic login from two aspects, one is the process of generating remember-me token, the other is the parsing process of the token.

3.1 Source code analysis of token generation

If we want to know how the remember-me automatic login token is generated in the source code, we first need to know how Spring Security enters the code where the token is located. The execution of this code is related to the authentication authorization of Spring Security described in the previous chapter. Please go to the front to check.

AbstractAuthenticationProcessingFilter#doFilter->

AbstractAuthenticationProcessingFilter#successfulAuthentication->

AbstractRememberMeServices#loginSuccess->

TokenBasedRememberMeServices#onLoginSuccess

The core processing method for this token generation is defined in: TokenBasedRememberMeServices#onLoginSuccess.

@ Overridepublic void onLoginSuccess (HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {/ / get the user name String username = retrieveUserName (successfulAuthentication) from the authentication object; / / get the password String password = retrievePassword (successfulAuthentication) from the authentication object;. If (! StringUtils.hasLength (password)) {/ / query the corresponding user UserDetails user = getUserDetailsService (). LoadUserByUsername (username) according to the user name; / / get the password password = user.getPassword () on the user;} / / obtain the login expiration time. The default is 2 weeks int tokenLifetime = calculateLoginLifetime (request, successfulAuthentication); long expiryTime = System.currentTimeMillis (); expiryTime + = 1000L * (tokenLifetime < 0? TWO_WEEKS_S: tokenLifetime); / generate remember-me signature information String signatureValue = makeTokenSignature (expiryTime, username, password); / / Save cookie setCookie (new String [] {username, Long.toString (expiryTime), signatureValue}, tokenLifetime, request, response);} protected String makeTokenSignature (long tokenExpiryTime, String username, String password) {String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey (); MessageDigest digest Digest = MessageDigest.getInstance ("MD5"); return new String (Hex.encode (digest.digest (data.getBytes ();}

The implementation logic of the above source code is easy to understand:

First extract the username / password from the successfully logged-in Authentication object

Since the password may have been erased after a successful login, if you do not get the password at first, reload the user from UserDetailsService and get the password again

Next, get the validity period of the token, which is two weeks by default.

Then call the makeTokenSignature () method to calculate the hash value, which is actually a hash value based on username, token validity, and password and key. If we do not set the key ourselves, it is set by default in the RememberMeConfigurer#getKey method, whose value is a UUID string. But if the server restarts, the default key will change, which will invalidate all remember-me automatic login tokens that were previously sent, so we can specify this key.

Finally, the user name, token validity, and the calculated hash value are put into Cookie and returned with response.

3.2 Source code analysis of token parsing

For RememberMe, Spring Security provides RememberMeAuthenticationFilter as a filter class to handle related functions. Let's take a look at the doFilter () method of RememberMeAuthenticationFilter:

Public void doFilter (ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res If (SecurityContextHolder.getContext (). GetAuthentication () = = null) {/ / handle the business logic of automatic login Authentication rememberMeAuth = rememberMeServices.autoLogin (request, response) If (rememberMeAuth! = null) {/ / Attempt authenticaton via AuthenticationManager try {rememberMeAuth = authenticationManager.authenticate (rememberMeAuth) / / Store to SecurityContextHolder SecurityContextHolder.getContext () .setAuthentication (rememberMeAuth); onSuccessfulAuthentication (request, response, rememberMeAuth) If (logger.isDebugEnabled ()) {logger.debug ("SecurityContextHolder populated with remember-me token:'" + SecurityContextHolder.getContext () .getAuthentication ()) + "'") } / / Fire event if (this.eventPublisher! = null) {eventPublisher .publishEvent (new InteractiveAuthenticationSuccessEvent (SecurityContextHolder.getContext () .getAuthentication ()) This.getClass ()) } if (successHandler! = null) {successHandler.onAuthenticationSuccess (request, response, rememberMeAuth) Return }} catch (AuthenticationException authenticationException) {if (logger.isDebugEnabled ()) {logger.debug ( "SecurityContextHolder not populated with remember-me token As "+" AuthenticationManager rejected Authentication returned by RememberMeServices:'"+ rememberMeAuth + "' Invalidating remember-me token ", authenticationException);} rememberMeServices.loginFail (request, response) OnUnsuccessfulAuthentication (request, response, authenticationException);}} chain.doFilter (request, response) } else {if (logger.isDebugEnabled ()) {logger.debug ("SecurityContextHolder not populated with remember-me token, as it already contained:'" + SecurityContextHolder.getContext (). GetAuthentication () + "") } chain.doFilter (request, response);}}

The most important thing about this method is that if the currently logged-in user instance cannot be obtained from SecurityContextHolder, then call the rememberMeServices.autoLogin () logic to log in. Let's take a look at this method:

@ Override public final Authentication autoLogin (HttpServletRequest request, HttpServletResponse response) {String rememberMeCookie = extractRememberMeCookie (request); if (rememberMeCookie = = null) {return null;} logger.debug ("Remember-me cookie detected") If (rememberMeCookie.length () = = 0) {logger.debug ("Cookie was empty"); cancelCookie (request, response); return null;} UserDetails user = null; try {String [] cookieTokens = decodeCookie (rememberMeCookie) User = processAutoLoginCookie (cookieTokens, request, response); userDetailsChecker.check (user); logger.debug ("Remember-me cookie accepted"); return createSuccessfulAuthentication (request, user);}. CancelCookie (request, response); return null;}

Spring Security is here to extract the cookie information and decode the cookie information. After decoding, the processAutoLoginCookie () method is called to do the verification. I won't post the code of the processAutoLoginCookie () method. The core process is to first get the user name and expiration time, then query the user password based on the user name, and then calculate the hash value through the MD5 hash function. Finally, by comparing the hash value obtained with the hash value passed by the browser, you can confirm whether the token is valid, and then confirm whether the login is valid.

On Spring Security hash encryption on how to achieve automatic login function to share here, I hope that the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report