色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

Spring Security入門demo案例

瀏覽:8日期:2023-12-13 17:35:56
目錄一、簡介二、入門案例三、自定義認(rèn)證邏輯四、自定義授權(quán)邏輯五、注銷登錄六、記住我功能七、會話管理一、簡介

Spring Security是一個(gè)高度自定義的安全框架。利用Spring IoC/DI和AOP功能,為系統(tǒng)提供了聲明式安全訪問控制功能,減少了為系統(tǒng)安全而編寫大量重復(fù)代碼的工作。主要包含如下幾個(gè)重要的內(nèi)容:

認(rèn)證(Authentication),系統(tǒng)認(rèn)為用戶是否能登錄。 授權(quán)(Authorization),系統(tǒng)判斷用戶是否有權(quán)限去做某些事情。二、入門案例

首先引入必要的依賴:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>

然后創(chuàng)建一個(gè)controller:

@Slf4j@RestControllerpublic class SecurityController { @GetMapping({'/', '/index'}) public String getLogin() {log.info('進(jìn)入index');return 'index'; }}

此時(shí),我們的入門案例就完成了。啟動項(xiàng)目,Spring Security默認(rèn)就開啟了,此時(shí)訪問localhost:8080/index就會被Spring Security攔截,跳轉(zhuǎn)到內(nèi)置的登錄頁面要求登錄。

默認(rèn)情況下,登錄的用戶名為user,密碼在啟動項(xiàng)目的時(shí)候,控制臺有打印出來:

Using generated security password: 0bfad04b-7a47-40fb-ae15-2a4a7c57099b

使用如上的賬密登錄后,再次訪問localhost:8080/index就可以正常返回預(yù)期的內(nèi)容index了。

如果我們不希望使用默認(rèn)的用戶密碼,可以在配置文件中指定一個(gè),如此Spring Security就會使用我們指定的,而不會使用默認(rèn)的了。

spring.security.user.name=zhangxunspring.security.user.password=123123三、自定義認(rèn)證邏輯

當(dāng)我們開啟自定義認(rèn)證邏輯后,上面的默認(rèn)用戶和配置文件中的用戶就不生效了,可以先行刪除。

我們新建一個(gè)MySecurityConfig類,并繼承WebSecurityConfigurerAdapter類,用于自定義認(rèn)證邏輯。

@EnableWebSecuritypublic class MySecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception {// 指定使用BCryptPasswordEncoder對前端傳過來的明文密碼進(jìn)行encodePasswordEncoder encoder = new BCryptPasswordEncoder();// 用戶的真實(shí)密碼需要encode,security是比較兩個(gè)密文是否一致auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser('root').password(encoder.encode('root123')).roles(); }}

需要注意的是,密碼必須使用如上的PasswordEncoder進(jìn)行編碼,否則會拋出如下錯(cuò)誤:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id 'null'

此時(shí),我們重啟應(yīng)用,訪問localhost:8080/index進(jìn)入內(nèi)置的登錄頁面,輸入root/root123之后就能正常返回index內(nèi)容了。

四、自定義授權(quán)邏輯

一般權(quán)限管理都是基于RBAC模型的,即登錄的用戶肯定擁有某些角色,這些角色允許訪問某些資源。我們先來改造下認(rèn)證的邏輯:

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder encoder = new BCryptPasswordEncoder(); auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser('root').password(encoder.encode('root123')).roles('admin','manager').and().withUser('manager').password(encoder.encode('mm000')).roles('manager');}

使得root用戶擁有admin和manager兩個(gè)角色,zhang用戶擁有manager一個(gè)角色。

然后我們在該配置類中再增加自定義授權(quán)的邏輯:

@Overrideprotected void configure(HttpSecurity http) throws Exception { http.authorizeRequests()// 任何角色允許訪問.antMatchers('/', '/index').permitAll()// 僅admin角色可以訪問.antMatchers('/admin/**').hasRole('admin')// admin和manager兩個(gè)角色可以訪問.antMatchers('/manager/**').hasAnyRole('admin', 'manager'); // 沒有權(quán)限則進(jìn)入內(nèi)置的登錄頁面 http.formLogin();}

然后為了測試,我們還需要增加幾個(gè)資源:

@Slf4j@RestControllerpublic class SecurityController { @GetMapping({'/', '/index'}) public String getLogin() {log.info('進(jìn)入index');return 'index'; } @GetMapping('admin/getHello') public String getAdminHello(){return 'hello admin!'; } @GetMapping('manager/getHello') public String getManagerHello(){return 'hello manager!'; } @GetMapping('guest/getHello') public String getGuestHello(){return 'hello guest!'; }}

此時(shí),重啟項(xiàng)目,我們發(fā)現(xiàn):

訪問/,/index,/guest/**的資源直接就能返回,不需要認(rèn)證和授權(quán)。 訪問/admin/**資源的時(shí)候,由于沒有登錄,會跳轉(zhuǎn)到內(nèi)置的登錄頁面;如果已經(jīng)登錄,只有root用戶登錄后才可以訪問; 訪問/admin/**資源的時(shí)候,由于沒有登錄,會跳轉(zhuǎn)到內(nèi)置的登錄頁面;如果已經(jīng)登錄,那么root和zhang用戶都能訪問;

我們還可以定制自己的登錄頁面,用于替換Spring Security內(nèi)置的登錄頁面,這塊需要定制html頁面,本文不再詳述,比較簡單,可以參考formLogin的源碼注釋,里面講的比較清楚。

五、注銷登錄

因?yàn)槲覀兪褂玫氖荢pring Security內(nèi)置的登錄頁面,各個(gè)資源返回的也是json字符串,并非頁面,所以如何實(shí)現(xiàn)注銷登錄是個(gè)問題。但可以通過閱讀HttpSecurity:logout中的源碼注釋,我們基本就能學(xué)會怎么操作了。

注銷登錄默認(rèn)就開啟了,默認(rèn)是訪問/logout,和/login一樣都是Spring Security自己實(shí)現(xiàn)的,我們調(diào)用即可; 注銷登錄會清除服務(wù)器端的session,清除remember me等設(shè)置;這個(gè)后面再詳細(xì)解說; 注銷登錄后默認(rèn)會跳轉(zhuǎn)到/login頁面;

還是如上的案例,我們在登錄后,直接調(diào)用http://localhost:8080/logout就可以實(shí)現(xiàn)上述的注銷登錄功能了。

但是在有些時(shí)候,我們會自定義登出的URL以及成功登出后應(yīng)該跳轉(zhuǎn)到哪個(gè)URL,Spring Security也支持我們進(jìn)行自定義。

@Override protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()// 任何角色允許訪問.antMatchers('/', '/index').permitAll()// 僅admin角色可以訪問.antMatchers('/admin/**').hasRole('admin')// admin和manager兩個(gè)角色可以訪問.antMatchers('/manager/**').hasAnyRole('admin', 'manager');// 沒有權(quán)限進(jìn)入內(nèi)置的登錄頁面http.formLogin();// 自定義登出邏輯http.logout().logoutUrl('/myLogOut').logoutSuccessUrl('/index'); }

當(dāng)Post方式請求/myLogOut的時(shí)候就會觸發(fā)Spring Security的登出邏輯,并且登出后會跳轉(zhuǎn)到/index界面。

注意:在本案例中,是使用瀏覽器進(jìn)行測試的,而且沒有html的頁面,所以使用瀏覽器發(fā)起post請求比較困難,那么使用get請求發(fā)起可以嗎?默認(rèn)是不行的,因?yàn)镾pring Security默認(rèn)開啟了CSRF校驗(yàn),所有改變狀態(tài)的請求都必須以POST方式提交,為了能驗(yàn)證我們這個(gè)例子,我們需要把CSRF校驗(yàn)關(guān)掉,即在如上logout代碼后面加上如下的配置:

// 暫時(shí)關(guān)閉CSRF校驗(yàn),允許get請求登出http.csrf().disable();

此時(shí)再重啟應(yīng)用,就可以驗(yàn)證localhost:8080/myLogOut的登出邏輯了。

六、記住我功能

當(dāng)我們沒有開啟記住我功能的時(shí)候,登錄root用戶后,如果關(guān)掉瀏覽器,重新打開網(wǎng)址,會發(fā)現(xiàn)登錄已經(jīng)退出了,這是因?yàn)榈卿浶畔⒅辉诋?dāng)前會話有效。

如果我們想要在某個(gè)時(shí)間段以內(nèi),一直使root用戶處于登錄狀態(tài),那么就需要在瀏覽器端設(shè)置一個(gè)cookie,在有效期內(nèi),這個(gè)cookie所屬的用戶就一直是登錄的狀態(tài)。同樣的,只要在上面注銷登錄的代碼后面加上:

// 開啟remember me功能,有效期默認(rèn)14天http.rememberMe();

此時(shí)內(nèi)置的登錄頁面會出現(xiàn)記住我的選擇框,當(dāng)我們選擇上登錄后,瀏覽器端就會有當(dāng)前用戶的cookie信息了(名稱為remember-me),在它過期之前,登錄狀態(tài)就一直有效。

需要用戶主動退出登錄,也就是調(diào)用我們上面的/myLogOut才能將cookie清除并退出登錄。

如果是自定義的登錄頁面,可以在后面鏈?zhǔn)秸{(diào)用rememberMeParameter()方法,傳入自己的rememberme參數(shù)名稱即可。

以上是關(guān)于Spring Security的基本使用方法,使用數(shù)據(jù)庫及其它特性將會在后面的文章中予以說明。

七、會話管理

在以上例子中,認(rèn)證和授權(quán)都是Spring Security自動進(jìn)行的。但是有的時(shí)候我們需要管理會話,比如從會話中獲取用戶姓名、用戶的權(quán)限信息;會話策略選擇以及會話超時(shí)設(shè)置等。

我們只需要增加如下的方法即可:

private String getName(){Authentication authentication = SecurityContextHolder.getContext().getAuthentication();Object principal = authentication.getPrincipal();if(principal == null){ return '游客';}if(principal instanceof UserDetails){ UserDetails userDetails = (UserDetails) principal; return userDetails.getUsername();} else{ return principal.toString();} }

該方法使用SecurityContextHolder獲取上下文信息,然后再獲取到其中的用戶名即可,當(dāng)然其中還提供了可以獲取密碼、權(quán)限信息等方法。

Session的管理策略有以下幾種:

always,如果沒有Session就會創(chuàng)建一個(gè); ifRequired,登錄時(shí)如果有需要,就創(chuàng)建一個(gè); never,不會主動創(chuàng)建session,如果其它地方創(chuàng)建了session,就會使用它; stateless,不會創(chuàng)建也不會使用session;

其中ifRequired是默認(rèn)的模式,stateless是采用token機(jī)制時(shí),session禁用的模式,設(shè)置方法如下:

@Override protected void configure(HttpSecurity http) throws Exception {http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); }

至于session的超時(shí)和安全可以在配置文件中設(shè)置:

# 超時(shí)時(shí)間設(shè)置server.servlet.session.timeout=3600s# 瀏覽器腳本將無法訪問cookieserver.servlet.session.cookie.http‐only=true# cookie將僅通過HTTPS連接發(fā)送server.servlet.session.cookie.secure=true

到此這篇關(guān)于Spring Security入門demo案例的文章就介紹到這了,更多相關(guān)Spring Security入門內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 日本在线亚州精品视频在线 | 美女被躁免费视频软件 | 男人干女人的视频 | 国产成人免费在线视频 | 午夜免费片在线观看不卡 | 午夜日本一区二区三区 | 国产精品高清视亚洲一区二区 | 亚洲视频手机在线观看 | 嫩草影院在线观看网站成人 | 日产一一到六区网站免费 | 另类欧美日韩 | 成年人视频网站免费 | 国产成人99精品免费观看 | 欧美日韩一二区 | 91久久网 | 日本国产最新一区二区三区 | 成人中文字幕在线 | 步兵社区 | 综合自拍亚洲综合图区美腿丝袜 | 999热精品这里在线观看 | 国产成人久久精品激情91 | 一级毛片免费观看久 | 精品国产品香蕉在线观看 | 偷窥女厕国产在线视频 | 久久日本精品一区二区免费 | 久久爱wwwww 久久爱www成人 | 亚洲人成网址在线观看 | 欧美日韩在线观看区一二 | 九九精品视频一区在线 | 欧美成人免费tv在线播放 | 国产极品一区 | 三级全黄a | 色婷婷久久综合中文久久蜜桃 | 蜜桃88av| 不卡一区二区在线 | 国产一区二区三区亚洲欧美 | 日韩一级一欧美一级国产 | 中文字幕一区二区三区精品 | 欧美一级高清片欧美国产欧美 | 在线一区二区三区 | 精品久久一区二区 |