在第一篇的教程中,我們簡單的了解了一下 SpringSecurity 的使用姿勢,添加依賴,在application.yml
文件中加幾行配置,就可以實現一個基本的登錄認證;
默認的配置只能設置一個賬號,那么如果需要多個賬號可以怎么支持呢?
本文將介紹一下基於內存的認證方式
I. 內存認證
基於內存保存認證信息的方式,本篇博文中,會介紹兩種常見的使用姿勢
0. 項目配置
環境配置和前面一致,相關內容可以參考博文: 191223-SpringBoot 整合 SpringSecurity 之起源篇(零)
1. WebSecurityConfigurerAdapter
這里主要是借助SpringSecurity
的配置適配器來處理,下面是一個簡單的 case
@Configuration
public class SecurityAdapterConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 測試時,可以直接用下面的方式
// User.UserBuilder builder = User.withDefaultPasswordEncoder();
User.UserBuilder builder = User.builder().passwordEncoder(passwordEncoder()::encode);
auth.inMemoryAuthentication().withUser(builder.username("hui1").password("123456").roles("guest").build());
auth.inMemoryAuthentication().withUser(builder.username("hui2").password("123456").roles("guest").build());
}
}
主要邏輯在 configure
這個方法中,但是需要注意,我們額外的設置了密碼的加密方式, 當我們不設置這個的時候,實際登錄的時候會發現,即便你輸入了正確的用戶名密碼,也會提示失敗(歡迎各位大佬實測一下)
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
其次,在創建用戶的時候,需要注意的是,除了設置了用戶名和密碼之外,還給用戶加上了一個角色,這個會在后續文章的 RBAC(基於角色的授權)中介紹它的作用
2. UserDetailsService
這里介紹另外一種方式,在后面的 db 中保存認證信息時,也會用到;在 SpringSecurity 的實現中,通過 UserDetailService 這個 bean 來根據用戶名查詢對應的用戶信息;所以我們只需要實現一個我們自定義的 Bean 來替換默認的,就可以來實現我們的目標
我們的配置類如下
@Configuration
public class SecurityAutoConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 基於內存的認證方式
*
* @param passwordEncoder
* @return
*/
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
User.UserBuilder users = User.builder().passwordEncoder(passwordEncoder::encode);
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(users.username("1hui").password("123456").roles("guest").build());
manager.createUser(users.username("2hui").password("666666").roles("manager").build());
manager.createUser(users.username("3hui").password("root").roles("admin").build());
return manager;
}
}
3. 測試
上面兩種方式,都可以實現在內存中保存認證信息,接下來我們進入實測環節,首先寫一個 http 接口
@RestController
public class IndexRest {
public String getUser() {
// 獲取用戶信息
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userName;
if (principal instanceof UserDetails) {
userName = ((UserDetails) principal).getUsername();
} else {
userName = principal.toString();
}
return userName;
}
/**
* @return
*/
@GetMapping(path = {"/"})
public String index() {
return "hello this is index! welcome " + getUser();
}
}
在實際測試時,上面兩種 case 都是 ok 的,下面的演示過程主要是基於第二種方式給出的示例
II. 其他
0. 系列博文&項目源碼
博文
源碼
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源碼: - https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-security/001-authentication-mem-config - https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-security/001-authentication-mem-userdetail
1. 一灰灰 Blog
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛
- 一灰灰 Blog 個人博客 https://blog.hhui.top
- 一灰灰 Blog-Spring 專題博客 http://spring.hhui.top