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

What is the use and principle of SpringSecurityRememberme

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

What is the use and principle of SpringSecurityRememberme? for this question, this article introduces the corresponding analysis and solution in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible way.

The Remember me function is to log in once after checking "remember me", and then be exempted from login during the validity period.

First, let's look at the specific configuration:

Pom file:

Org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-security

Configuration of Security:

@ Autowired private UserDetailsService myUserDetailServiceImpl; / / user Information Service @ Autowired private DataSource dataSource / / data source @ Override protected void configure (HttpSecurity http) throws Exception {/ / formLogin () is the default login form page. If loginPage (url) is not configured, spring security / / default login page is used. If loginPage () is configured, log in using the custom login page http.formLogin () / / form .loginPage (SecurityConst.AUTH_REQUIRE) .loginProcessingUrl (SecurityConst.AUTH_FORM) / / url intercepted by login requests That is, action .roomHandler (loginSuccessHandler) .failureHandler (loginFailureHandler) .and () .remember me () .userDetailsService (myUserDetailServiceImpl) / set userDetailsService .tokenReposito ry (persistentTokenRepository ()) / set the data access layer .tokenValiditySeconds (60 * 60) / remember my time (seconds) .and () .authorizeRequests () / a pair of request authorization .antMatches (SecurityConst.AUTH_REQUIRE) SecurityProperty.getBrowser () .getLoginPage ()) .permitAll () / / allows everyone to access login.html and custom login pages .anyRequest () / any request .authenticated () / requires authentication .and () .csrf () .disable () / turns off cross-site forgery } / * * persistent token * * Security, the default is to use InMemoryTokenRepositoryImpl, a subclass of PersistentTokenRepository, to put token in memory * if JdbcTokenRepositoryImpl is used, a table persistent_logins will be created and the token will be persisted to the database * / @ Bean public PersistentTokenRepository persistentTokenRepository () {JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl (); tokenRepository.setDataSource (dataSource); / / set the data source / / tokenRepository.setCreateTableOnStartup (true); / / start the creation of the table, and comment out return tokenRepository;} after successful creation

The above myUserDetailServiceImpl is a self-implemented UserDetailsService interface, and dataSource automatically reads the database configuration. 3600 seconds, or one hour, set by the expiration time

Add a line to the login page (name must be remeber-me):

Basic principles of "remember me":

1. When the authentication request is sent for the first time, it will be intercepted by UsernamePasswordAuthenticationFilter and then authenticated.

After successful authentication, there is a RememberMeServices interface in AbstracAuthenticationProcessingFilter.

The default implementation class for this interface is NullRememberMeServices, where another implementation abstract class, AbstractRememberMeServices, is called.

/ /... Private RememberMeServices rememberMeServices = new NullRememberMeServices (); protected void successfulAuthentication (HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {/ /. SecurityContextHolder.getContext () .setAuthentication (authResult); / / after logging in successfully, call RememberMeServices to save Token related information rememberMeServices.loginSuccess (request, response, authResult); / /.}

2. Call the loginSuccess method of AbstractRememberMeServices.

You can see that the following onLoginSuccess () method is called only if name is "remember-me" and true in request. This is why the form in the login page above, name must be "remember-me":

3. After configuring rememberMe () in Security, PersistentTokenBasedRememberMeServices will implement the abstract method in the parent class AbstractRememberMeServices.

In PersistentTokenBasedRememberMeServices, there is a PersistentTokenRepository that generates a Token and writes the Token into cookie to return to the browser. The default implementation class for PersistentTokenRepository is InMemoryTokenRepositoryImpl, which saves the token to memory. Here we configure another implementation class, JdbcTokenRepositoryImpl, which persists the Token to the database

/ /... Private PersistentTokenRepository tokenRepository = new InMemoryTokenRepositoryImpl (); protected void onLoginSuccess (HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {String username = successfulAuthentication.getName (); logger.debug ("Creating new persistent login for user" + username); / / create a PersistentRememberMeToken PersistentRememberMeToken persistentToken = new PersistentRememberMeToken (username, generateSeriesData (), generateTokenData (), new Date ()); try {/ / Save Token tokenRepository.createNewToken (persistentToken); / / write Token to Cookie addCookie (persistentToken, request, response) } catch (Exception e) {logger.error ("Failed to save persistent token", e);}}

4. JdbcTokenRepositoryImpl persists Token to the database

/ * * The default SQL used by createNewToken * / public static final String DEF_INSERT_TOKEN_SQL = "insert into persistent_logins (username, series, token, last_used) values"; public void createNewToken (PersistentRememberMeToken token) {getJdbcTemplate (). Update (insertTokenSql, token.getUsername (), token.getSeries (), token.getTokenValue (), token.getDate ());}

Looking at the database, you can see that a piece of data has been inserted into persistent_logins:

5. Restart the service and send the second authentication request, only Cookie will be carried.

So it will be intercepted by RememberMeAuthenticationFilter directly, and there is no authentication information in memory at this time.

As you can see, RememberMeServices is implemented by PersistentTokenBasedRememberMeServices at this time.

6. In PersistentTokenBasedRememberMeServices, call the processAutoLoginCookie method to obtain user-related information

Protected UserDetails processAutoLoginCookie (String [] cookieTokens, HttpServletRequest request, HttpServletResponse response) {if (cookieTokens.length! = 2) {throw new InvalidCookieException ("Cookie token did not contain" + 2 + "tokens, but contained'" + Arrays.asList (cookieTokens) + "'");} / / get Series and Token final String presentedSeries = cookieTokens [0] from Cookie; final String presentedToken = cookieTokens [1]; / / query PersistentRememberMeToken PersistentRememberMeToken token = tokenRepository .getTokenForSeries (presentedSeries) through Series in the database If (token = = null) {throw new RememberMeAuthenticationException ("No persistent token found for series id:" + presentedSeries);} / verify whether the Token in Token and Cookie in the database is the same if (! presentedToken.equals (token.getTokenValue () {tokenRepository.removeUserTokens (token.getUsername ()); throw new CookieTheftException (messages.getMessage ("PersistentTokenBasedRememberMeServices.cookieStolen", "Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack. ");} / / determine whether Token times out if (token.getDate (). GetTime () + getTokenValiditySeconds () * 1000L < System .currentTimeMillis ()) {throw new RememberMeAuthenticationException (" Remember-me login has expired ");} if (logger.isDebugEnabled ()) {logger.debug (" Refreshing persistent login token for user'"+ token.getUsername () +", series'"+ token.getSeries () +") } / / create a new PersistentRememberMeToken PersistentRememberMeToken newToken = new PersistentRememberMeToken (token.getUsername (), token.getSeries (), generateTokenData (), new Date ()); try {/ / update Token tokenRepository.updateToken (newToken.getSeries (), newToken.getTokenValue (), newToken.getDate ()) in the database; / / rewrite to Cookie addCookie (newToken, request, response);} catch (Exception e) {logger.error ("Failed to update token:", e) Throw new RememberMeAuthenticationException ("Autologin failed due to data access problem");} / / call UserDetailsService to get user information return getUserDetailsService (). LoadUserByUsername (token.getUsername ());}

7. After obtaining the relevant information of the user, call AuthenticationManager to authenticate the authorization

The answer to the question about the use and principle of SpringSecurityRememberme is shared here. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel for more related knowledge.

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