亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringSecurity自動登錄流程與實現(xiàn)詳解

 更新時間:2024年01月04日 09:31:09   作者:Splaying  
這篇文章主要介紹了SpringSecurity自動登錄流程與實現(xiàn)詳解,所謂的自動登錄是在訪問鏈接時瀏覽器自動攜帶上了Cookie中的Token交給后端校驗,如果刪掉了Cookie或者過期了同樣是需要再次驗證的,需要的朋友可以參考下

1、自動登錄原理

在這里插入圖片描述

大概的流程是這樣一個圖,里面還有很多細節(jié)與類下面進行分析

1.1、首次登錄

  1. 第一次登錄時首先需要勾選checkbox的組件,頁面中應該給出一個記住我的勾選框!
  2. 然后Security會放行到AbstractAuthenticationProcessingFilter抽象類,這個類里面doFilter放行鏈主要調(diào)用attemptAuthentication方法、successfulAuthentication方法。
  3. 其中attemptAuthentication方法由UsernamePasswordAuthenticationFilter類實現(xiàn),這里會調(diào)用自定義的UseDetailsService接口的實現(xiàn)類(用戶登錄賬號密碼驗證),也就是說這個方法會進行賬號密碼的校驗!
  4. successfulAuthentication方法主要是在用戶驗證通過之后用于Token的生成、存儲;其中會用到PersistentTokenBasedRememberMeServices類中的onLoginSuccess方法
  5. onLoginSuccess方法核心就是隨機生成一個Token、將Token持久化到數(shù)據(jù)庫中、并且將Token寫入到Cookie中!
@Override
protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
		Authentication successfulAuthentication) {
	// 1. 登錄的用戶名賬號	
	String username = successfulAuthentication.getName();
	// 2. 生成一個Token
	PersistentRememberMeToken persistentToken = new PersistentRememberMeToken(username, generateSeriesData(),
			generateTokenData(), new Date());
	try {
		// 3. 持久化到數(shù)據(jù)庫中
		this.tokenRepository.createNewToken(persistentToken);
		// 4. 添加到Cookie中
		addCookie(persistentToken, request, response);
	}
	catch (Exception ex) {
		this.logger.error("Failed to save persistent token ", ex);
	}
}

這里的Token可以通過代碼進行設置過期時間、像什么十天內(nèi)免登錄、三天內(nèi)免登錄…

1.2、自動登錄

  1. 所謂的自動登錄是在訪問鏈接時瀏覽器自動攜帶上了Cookie中的Token交給后端校驗,如果刪掉了Cookie或者過期了同樣是需要再次驗證的!
  2. 瀏覽器攜帶Token進行請求來到RememberMeAuthenticationFilter類中的doFilter方法過濾鏈中;這里調(diào)用AbstractRememberMeServices抽象類中的autoLogin方法
  3. autoLogin方法中會從request中拿到cookie的值,然后調(diào)用processAutoLoginCookie方法進行數(shù)據(jù)庫層面的校驗!
  4. processAutoLoginCookie方法是由PersistentTokenBasedRememberMeServices類給出實現(xiàn);首先通過Token查到對應的登錄賬戶名。
  5. 如果匹配失敗直接攔截掉請求,否則匹配成功那么重新刷新Token的過期時間并且重新持久化并且寫到Cookie中,并且調(diào)用自定義的UseDetailsService接口的實現(xiàn)類(用戶登錄賬號密碼驗證)。
@Override
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
		HttpServletResponse response) {
	// 1. cookie殘缺	
	if (cookieTokens.length != 2) {
		throw new InvalidCookieException("Cookie token did not contain " + 2 + " tokens, but contained '"
				+ Arrays.asList(cookieTokens) + "'");
	}
	String presentedSeries = cookieTokens[0];
	String presentedToken = cookieTokens[1];
	PersistentRememberMeToken token = this.tokenRepository.getTokenForSeries(presentedSeries);
	
	....
	// 2. 這里有一大堆的校驗失敗
	....
	
	// 3. 校驗成功,重新生成Cookie等一系列操作
	PersistentRememberMeToken newToken = new PersistentRememberMeToken(token.getUsername(), token.getSeries(),
			generateTokenData(), new Date());
	try {
		this.tokenRepository.updateToken(newToken.getSeries(), newToken.getTokenValue(), newToken.getDate());
		addCookie(newToken, request, response);
	}
	
	// 4. 查用戶(因為有可能用戶刪除掉)
	return getUserDetailsService().loadUserByUsername(token.getUsername());
}

分析:最后為什么要重新查詢一次用戶?因為Token查詢的是表中一個Token + Username的表,并不是用戶登錄賬號表;有可能Token沒過期但是刪除掉了這個用戶,Token中有殘余數(shù)據(jù)!

2、具體實現(xiàn)

前言:首先需要看一下JdbcTokenRepositoryImpl類的源碼,這個類的源碼里給出了存放token、用戶名,時間戳等一系列參數(shù)的建表語句;以及操作數(shù)據(jù)庫的語句。

在這里插入圖片描述

2.1、創(chuàng)建數(shù)據(jù)表

  • 創(chuàng)建數(shù)據(jù)表可以自己創(chuàng)建,也可以在服務啟動時讓其自動創(chuàng)建
  • 這里選擇自動創(chuàng)建表,直接把它的源碼復制過來;表名、列名一些參數(shù)最好不要動。
// 操作token的數(shù)據(jù)表
create table persistent_logins (
    username varchar(64) not null, 
    series varchar(64) primary key, 
    token varchar(64) not null, 
    last_used timestamp not null
)engine=innodb default charset=utf8

// 存放用戶信息表
create table `account` (
  `id` int(11) not null auto_increment comment '編號',
  `username` varchar(30) not null comment '姓名',
  `password` varchar(30) not null comment '密碼',
  `role` varchar(100) not null comment '權(quán)限',
  primary key (`id`)
) engine=innodb default charset=utf8
insert into account(`id`, `username`, `password`, `role`) values (1, 'admin', '123456', 'root')


2.2、UserDetailsService實現(xiàn)

編寫Pojo類對應數(shù)據(jù)庫中的表

// pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {

    private Integer id;
    private String username;
    private String password;
    private String role;
}

編寫mapper用戶操作數(shù)據(jù)庫的接口

// mapper
@Mapper
@Repository
public interface AccountMapper {

    Account getLoginAccount(String username);
}

編寫mapper用戶操作數(shù)據(jù)庫的接口

// accountmapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.splay.mapper.AccountMapper">
    
    <select id="getLoginAccount" parameterType="string" resultType="Account">
        select *from account where username = #{username}
    </select>
</mapper>

編寫UserDetailsService接口的實現(xiàn)類,注入Mapper

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    // 注入dao層
    @Autowired
    AccountMapper mapper;

    @Autowired
    BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
        Account account = mapper.getLoginAccount(username);
        System.out.println(account.toString());
        List<GrantedAuthority> list = new ArrayList<>();
        // SpringSecurity權(quán)限控制角色需要使用"ROLE_"開頭, 并且密碼在構(gòu)造時需要進行加密。
        list.add(new SimpleGrantedAuthority("ROLE_" + account.getRole()));

        return new User(passwordEncoder.encode(account.getUsername()), passwordEncoder.encode(account.getPassword()), list);
    }
}

2.3、Security配置

Security中首先需要注入BCryptPasswordEncoder加密解密類、數(shù)據(jù)源DataSource、JdbcTokenRepositoryImpl操作Token的驅(qū)動類、以及UserDetailsService類(也可以在其他Configuration中注入)

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	// 數(shù)據(jù)源
	@Autowired
    DataSource dataSource;

	// UserDetailsService實現(xiàn)類
	@Autowired
    UserDetailsService userDetailsService;

    // 注入密碼加密解密類
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    // 注入jdbc Token操作類
    @Bean
    PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        repository.setCreateTableOnStartup(false);				//關(guān)閉自動創(chuàng)建表
        repository.setDataSource(dataSource);					//注入數(shù)據(jù)源
        return repository;
    }
		
}

配置用戶登錄密碼校驗,這里就是查詢數(shù)據(jù)庫校驗賬號密碼的有效性

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

	// 密碼需要進行加密解密進行驗證匹配!
	auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}

配置登錄、登出、記住我、Cookie有效時間

@Override
protected void configure(HttpSecurity http) throws Exception {
	http
        .formLogin()
        .loginPage("/login")                    // 登錄頁面
        .loginProcessingUrl("/user/login")      // 提交表單處理的請求,由Security實現(xiàn)
        .defaultSuccessUrl("/index",true).permitAll()      //成功訪問哪里
    .and()
        .logout()
        .logoutUrl("/logout")
        .logoutSuccessUrl("/index").deleteCookies().permitAll()    //退出成功頁面

    // 2. 無需保護的頁面
    .and()
        .authorizeRequests()
            .antMatchers("/level1/**").permitAll()
            .antMatchers("/level2/**").hasAnyRole("customer", "admin")
            .antMatchers("/level3/**").hasRole("admin")
    .anyRequest().authenticated().and()
            .rememberMe()                                       //記住我
            .tokenRepository(persistentTokenRepository)         //注入操作token的jdbc
            .tokenValiditySeconds(60).rememberMeCookieName("remember-me")                   //Cookie有效時間 單位: 秒
            .userDetailsService(userDetailsService);             //注入用戶驗證UserDetailsService
    http.exceptionHandling().accessDeniedPage("/nodeny");
    http.csrf().disable();
}

2.4、編寫前端登錄頁面

這里一定要開啟checkbox復選框,并且這個name = “remember-me”。

<form action="/user/login" method="post">
    用戶名: <input type="text" name="username"><br/>
    密碼: <input type="text" name="password"><br/>
    <input type="checkbox" name="remember-me">記住我<br/>
    <input type="submit" value="登錄"/>
</form>

到此這篇關(guān)于SpringSecurity自動登錄流程與實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)SpringSecurity自動登錄流程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MybatisPlus開啟二級緩存的方法詳解

    MybatisPlus開啟二級緩存的方法詳解

    這篇文章主要介紹了MybatisPlus開啟二級緩存的方法詳解,二級緩存是基于mapper文件的namespace級別,也就是說多個sqlSession可以共享一個mapper中的二級緩存區(qū)域,需要的朋友可以參考下
    2023-11-11
  • mybatis plus in方法使用詳解

    mybatis plus in方法使用詳解

    這篇文章主要介紹了mybatis plus in方法使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java8 Collectors求和功能的自定義擴展操作

    Java8 Collectors求和功能的自定義擴展操作

    這篇文章主要介紹了Java8 Collectors求和功能的自定義擴展操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Springboot+Stomp協(xié)議實現(xiàn)聊天功能

    Springboot+Stomp協(xié)議實現(xiàn)聊天功能

    本示例實現(xiàn)一個功能,前端通過websocket發(fā)送消息給后端服務,后端服務接收到該消息時,原樣將消息返回給前端,前端技術(shù)棧html+stomp.js,后端SpringBoot,需要的朋友可以參考下
    2024-02-02
  • 使用Spring CROS解決項目中的跨域問題詳解

    使用Spring CROS解決項目中的跨域問題詳解

    這篇文章主要介紹了使用Spring CROS解決項目中的跨域問題詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • Maven 項目生成jar運行時提示“沒有主清單屬性”

    Maven 項目生成jar運行時提示“沒有主清單屬性”

    這篇文章主要介紹了Maven 項目生成jar運行時提示“沒有主清單屬性”,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • 如何用Java注解和反射實現(xiàn)依賴注入

    如何用Java注解和反射實現(xiàn)依賴注入

    這篇文章主要介紹了如何用Java注解和反射實現(xiàn)依賴注入,對依賴注入感興趣的同學,可以實驗一下
    2021-05-05
  • 利用openoffice+jodconverter-code-3.0-bate4實現(xiàn)ppt轉(zhuǎn)圖片

    利用openoffice+jodconverter-code-3.0-bate4實現(xiàn)ppt轉(zhuǎn)圖片

    這篇文章主要為大家詳細介紹了利用openoffice+jodconverter-code-3.0-bate4實現(xiàn)ppt轉(zhuǎn)圖片,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Java中ThreadLocal的用法及原理詳解

    Java中ThreadLocal的用法及原理詳解

    這篇文章主要介紹了Java中ThreadLocal的用法及原理詳解,在并發(fā)編程中,如果一個類變量被多個線程操作,會造成線程安全問題,使用ThreadLocal可以讓每個線程擁有線程內(nèi)部的變量,防止多個線程操作一個類變量造成的線程安全問題,需要的朋友可以參考下
    2023-09-09
  • Java實現(xiàn)的最大匹配分詞算法詳解

    Java實現(xiàn)的最大匹配分詞算法詳解

    這篇文章主要介紹了Java實現(xiàn)的最大匹配分詞算法,簡單說明了最大匹配分詞算法的原理并結(jié)合具體實例形式最大匹配分詞算法的實現(xiàn)方法與相關(guān)注意事項,需要的朋友可以參考下
    2017-09-09

最新評論