最新Spring Security的基于內(nèi)存用戶認(rèn)證方式
1. 前言
又是新的一周,博主繼續(xù)來給大家更新 Spring Security 實(shí)戰(zhàn)教程了,在上一個章節(jié)中我們詳細(xì)介紹了 Spring Security 的底層原理,本章節(jié)博主將帶著大家介紹如何在 Spring Security 中實(shí)現(xiàn)基于內(nèi)存的用戶認(rèn)證。
雖然 Spring Security 基于內(nèi)存的用戶認(rèn)證,實(shí)際開發(fā)來說相對來說用的比較少,但某些場景下(如:開發(fā)階段、原型驗(yàn)證、演示環(huán)境搭建、單元測試/集成測試、或甚至不需要數(shù)據(jù)庫的簡單系統(tǒng)),基于內(nèi)存的用戶認(rèn)證方式就足以滿足需求,為了應(yīng)對這樣需求,博主覺得還是要必要聊一聊基于內(nèi)存的用戶認(rèn)證。
2. 因何選擇內(nèi)存認(rèn)證?
就如前面說的場景,總結(jié)內(nèi)存認(rèn)證主要有以下幾個優(yōu)點(diǎn):
- 簡單快捷:配置簡單,不需要依賴數(shù)據(jù)庫或外部存儲,適用于快速構(gòu)建和測試。
- 易于調(diào)試:所有用戶信息存儲在代碼中,方便開發(fā)過程中快速定位問題。
- 適用于小型應(yīng)用:對于用戶數(shù)量較少的應(yīng)用或者臨時驗(yàn)證原型,內(nèi)存認(rèn)證是個不錯的選擇
當(dāng)然,內(nèi)存認(rèn)證也有局限性:用戶數(shù)據(jù)不持久化、無法擴(kuò)展到分布式系統(tǒng)等。因此,在生產(chǎn)環(huán)境中,通常會采用基于數(shù)據(jù)庫或其他外部認(rèn)證機(jī)制的方式。
與數(shù)據(jù)庫認(rèn)證對比
| 特性 | 內(nèi)存認(rèn)證 | 數(shù)據(jù)庫認(rèn)證 |
|---|---|---|
| 用戶存儲位置 | 應(yīng)用內(nèi)存 | 持久化存儲 |
| 用戶管理靈活性 | 配置硬編碼 | 動態(tài)增刪改查 |
| 生產(chǎn)環(huán)境適用性 | 不推薦 | 推薦 |
3. 基礎(chǔ)配置實(shí)戰(zhàn)
接下來在之前的Maven項(xiàng)目中還是創(chuàng)建第三個子模塊 memory-spring-security ,完整的maven項(xiàng)目結(jié)構(gòu)如下:

? 創(chuàng)建Spring Security配置文件
現(xiàn)在我們來創(chuàng)建一個Spring Security 配置文件 InMemorySecurityConfig
@Configuration
public class InMemorySecurityConfig {
// 手動配置用戶信息
@Bean
public UserDetailsService users() {
UserDetails user = User.withUsername("user")
.password("{noop}user") // {noop}表示不加密
.roles("USER")
.build();
UserDetails admin = User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build();
//可以繼續(xù)追加其它用戶...
UserDetails anonymous = User.withUsername("anonymous")
.password("{noop}anonymous")
.roles("ANONYMOUS")
.build();
return new InMemoryUserDetailsManager(user, admin, anonymous);
}
// 配置安全策略 并配置/admin/** 只允許ADMIN角色用戶訪問
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.
authorizeHttpRequests(authorize -> authorize
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.logout(withDefaults())
;
return http.build();
}
}配置說明
- 構(gòu)建UserDetailsService
創(chuàng)建兩個用戶信息分別是:admin、user ,并由InMemoryUserDetailsManager進(jìn)行在內(nèi)存中保存用戶數(shù)據(jù)- SecurityFilterChain
在SecurityFilterChain中,默認(rèn)采用了Spring Security表單登陸登出方式,并配置/admin/**請求路徑下需要管理員角色方可訪問
? 創(chuàng)建Controller測試
接下來我們創(chuàng)建用以測試的Controller :DemoMemoryController
@Controller
public class DemoMemoryController {
//返回用戶信息及角色權(quán)限
@GetMapping("/")
public ResponseEntity<Map<String, Object>> index(Authentication authentication) {
String username = authentication.getName();//用戶名
Object principal =authentication.getPrincipal();//身份
// 獲取用戶擁有的權(quán)限列表
List<String> roles = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.toList());
//返回用戶信息
return ResponseEntity.ok(Map.of(
"username", username,
"principal", principal,
"roles", roles));
}
//測試管理員權(quán)限
@GetMapping("/admin/view")
public ResponseEntity<String> admin() {
return ResponseEntity.ok("管理員ADMIN角色訪問ok");
}
}代碼說明
- 注入 Authentication 對象
在index方法中,通過方法參數(shù)直接注入Authentication對象,Spring Security會自動傳入當(dāng)前認(rèn)證信息。- 提取用戶信息
通過authentication.getName()獲取當(dāng)前登錄用戶的用戶名;通過authentication.getAuthorities()獲取用戶的權(quán)限列表,并將每個權(quán)限的 getAuthority() 值收集成一個字符串列表。
? 運(yùn)行測試
啟動項(xiàng)目訪問,登陸頁中分別測試兩個用戶登陸查看信息,如user用戶:

接下來嘗試使用user用戶訪問 /admin/view 路徑,會出現(xiàn) 403 訪問錯誤提示:即您無權(quán)訪問此地址
切換admin用戶登陸,繼續(xù)訪問 /admin/view 路徑,出現(xiàn) 管理員ADMIN角色訪問ok 文字顯示即代表管理員角色允許訪問
4. 追加密碼編碼器
在上述代碼中,我們使用了 password(“{noop}admin”) 聲明了密碼明文存儲,如果我們需要對密碼加密,如何操作? 實(shí)際上 Spring Security 為我們提供了非常方便的密碼編碼器
密碼編碼器配置
只需要創(chuàng)建 PasswordEncoder Bean,并返回加密類型,如下代碼樣例:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService users(PasswordEncoder encoder) {
UserDetails user = User.builder()
.username("user")
.password(encoder.encode("secret"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}支持的編碼格式:
# 不同前綴對應(yīng)不同編碼器
{noop} → NoOpPasswordEncoder (明文)
{bcrypt} → BCryptPasswordEncoder
{pbkdf2} → Pbkdf2PasswordEncoder
{scrypt} → SCryptPasswordEncoder
{sha256} → StandardPasswordEncoder
5. 總結(jié)
通過本章節(jié)的配置示例,相信你已經(jīng)可以使用 Spring Security 的基于內(nèi)存認(rèn)證方式來快速搭建安全認(rèn)證體系。
注意章節(jié)中提到的基于內(nèi)存的用戶認(rèn)證適用的場景,更多情況下還是建議使用 更為健全的認(rèn)證方式,如 基于數(shù)據(jù)庫的認(rèn)證、JWT 令牌認(rèn)證或 OAuth2,在下一章節(jié)我們將重點(diǎn)講述數(shù)據(jù)庫的認(rèn)證,敬請期待…
到此這篇關(guān)于最新Spring Security的基于內(nèi)存用戶認(rèn)證方式的文章就介紹到這了,更多相關(guān)Spring Security內(nèi)存用戶認(rèn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+Spring Security基于內(nèi)存用戶認(rèn)證的實(shí)現(xiàn)
- Spring Security內(nèi)存中認(rèn)證的實(shí)現(xiàn)
- SpringSecurity+Redis+Jwt實(shí)現(xiàn)用戶認(rèn)證授權(quán)
- Spring Security實(shí)現(xiàn)登錄認(rèn)證實(shí)戰(zhàn)教程
- SpringSecurity進(jìn)行認(rèn)證與授權(quán)的示例代碼
- springsecurity實(shí)現(xiàn)用戶登錄認(rèn)證快速使用示例代碼(前后端分離項(xiàng)目)
相關(guān)文章
SpringBoot Web詳解靜態(tài)資源規(guī)則與定制化處理
這篇文章主要介紹了SpringBoot web場景的靜態(tài)資源規(guī)則與定制化,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06
SpringBoot @SpringBootTest加速單元測試的小訣竅
這篇文章主要介紹了SpringBoot @SpringBootTest加速單元測試的小訣竅,具有很好的參考價值,對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
透徹理解Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區(qū)別
這篇文章主要介紹了Java中Synchronized(對象鎖)和Static Synchronized(類鎖)的區(qū)別,希望對大家有所幫助,一起跟隨小編過來看看吧2018-05-05
Java實(shí)現(xiàn)的文件上傳下載工具類完整實(shí)例【上傳文件自動命名】
這篇文章主要介紹了Java實(shí)現(xiàn)的文件上傳下載工具類,結(jié)合完整實(shí)例形式分析了java針對文件上傳下載操作的相關(guān)實(shí)現(xiàn)技巧,并且針對上傳文件提供了自動命名功能以避免文件命名重復(fù),需要的朋友可以參考下2017-11-11
詳解spring cloud Feign使用中遇到的問題總結(jié)
本篇文章主要介紹了詳解spring cloud Feign使用中遇到的問題總結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Java將不同的List集合復(fù)制到另一個集合常見的方法
在Java中,有時候我們需要將一個List對象的屬性值復(fù)制到另一個List對象中,使得兩個對象的屬性值相同,這篇文章主要介紹了Java將不同的List集合復(fù)制到另一個集合常見的方法,需要的朋友可以參考下2024-09-09
Java實(shí)現(xiàn)pdf轉(zhuǎn)圖片案例
這篇文章主要介紹了Java實(shí)現(xiàn)pdf轉(zhuǎn)圖片案例,按照步驟放置代碼,一步步完成該案例,將代碼部署便可,需要的朋友可以參考下2021-06-06

