網站首頁 編程語言 正文
Security前后端分離自定義登錄
思路:
通過自定義接口去處理前端的登錄請求,其主要問題就是如何實現登錄的認證!我們需要手動調用security的認證,并且在security配置類中需要定義一些東西
解決:
security配置類(我這里只是測試,根據個人使用更改即可):
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
// 查詢用戶信息
provider.setUserDetailsService(userDetailsService());
// 設置密碼加密算法
provider.setPasswordEncoder(passwordEncoder());
auth.authenticationProvider(provider);
}
@Bean
@Override
//構建用戶(可以從數據庫查找、內存模擬,這里為了方便就使用內存構建)
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("zhangsan").password("123456").authorities("p1").build());
manager.createUser(User.withUsername("lisi").password("123456").authorities("p2").build());
return manager;
}
@Bean
//生成密碼編碼類,像MD5,這里使用的這個是直接比較String
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
//security配置,核心
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
//訪問/test/1,需要p1權限
.antMatchers("/test/1").hasAnyAuthority("p1")
//訪問/test/2,需要p2權限
.antMatchers("/test/2").hasAnyAuthority("p2")
//test下的請求都必須認證(登錄)后才能訪問
.antMatchers("/test/**").authenticated()
//無條件放行test/** 以外的請求
.anyRequest().permitAll();
}
@Override
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
}
測試接口:
@RestController
public class TestController {
@Resource
AuthenticationManager authenticationManager;
@GetMapping("/mylogin")
public String test(String username, String password){
//生成驗證令牌
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,password);
//獲取驗證完成的認證信息
Authentication authenticate = authenticationManager.authenticate(token);
//保存到security上下文中
SecurityContextHolder.getContext().setAuthentication(authenticate);
return "登錄成功";
}
@GetMapping("/test/1")
public String test1(){
return "有p1權限,認證后才能看到這條消息";
}
@GetMapping("/test/2")
public String test2(){
return "有p2權限,認證后才能看到這條消息";
}
}
詳解:
1.配置類中此方法
為什么需要使用DaoAuthenticationProvider,使用為我們使用用戶名密碼是使用UsernamePasswordAuthenticationToken生成的驗證令牌(登錄接口中也是這樣寫的),而UsernamePasswordAuthenticationToken類型的驗證令牌最終會匹配到DaoAuthenticationProvider來進行驗證(因為只有他能驗證這種類型的)。
我們需要給這個驗證提供者(DaoAuthenticationProvider)提供用戶信息和密碼使用什么加密算法。
提供用戶信息即圖中:setUserDetailsService(),其中的userDetailsService()方法是你在配置類中定義的,里面你可以自定定義邏輯,比如最常用的數據庫查詢用戶信息
加密算法即圖中:setPasswordEncoder(),其中的passwordEncoder()方法也是在配置類中定義的,稍后會講解那一塊
2.配置類的userDetailsService()方法
這里是在內存中創建的數據,要查數據庫怎么玩??(見名知意它是個service,service掉dao就能拿到用戶信息了)
@Override
@Bean
protected UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
你需要寫一個類實現UserDetailsService,實現其方法loadUserByUsername(String username)即可,在這個方法里面你就可以調用dao去查這個用戶,并將其返回(返回類型是userdetails),所以用戶實體類必須繼承User類:如下介紹
是Security中的User類
import org.springframework.security.core.userdetails.User;
這個security中的User,該User實現了UserDetails,所以我們繼承即可。繼承之后我們只需要創建兩個
構造函數即可,它有錯誤提示,點一下就幫我們創建好了:
public class MyUser extends User {
private String userName;
private String password;
public MyUser(String username, String password, Collection extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public MyUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
}
3. 密碼加密方式
其作用是選擇一個密碼加密方式,就是在做密碼比對的時候,用什么加密方式去加密前端傳來的密碼,然后再和數據庫中的密碼比較!
4.注入AuthenticionManager
就是注入一個認證管理器,非要說些什么的話,就說說它是個什么吧。
AuthenticionManager是一個接口,看它的意思就知道它是管理認證的,該接口中也只有一個認證方法:
看看它的實現類
其實現類ProviderManager(它是做認證的,delegator結尾的是授權的。我也不敢確定說對沒有。。)就是我們用到的,它會幫我們找到能夠驗證的認證提供類(即DaoAuthenticionProvider)
5.我的登錄接口為啥用的get請求方式
不知道你們注意到我的登錄接口是get請求沒有,是這樣的:
因為我并沒有寫前端,我之前使用的post方式,我圖方便就在postman上測的,能夠登錄成功也確實認證成功,但是,并不能訪問需要身份認證后才能訪問的請求,我明明已經認證成功了呀?
是因為,認證成功之后,你的認證信息會被放到session中:
如圖,這是security初始化內部實例時(springboot啟動的時候),使用的就是httpsession,你要問在哪用到了這個repo:
我們只需要在接口中,將認證信息保存到security上下文即可,后續就交給security處理:
所以,你必須在同一個瀏覽器中先登錄認證才能有這個session,也就才能訪問得到你有權訪問的請求(當然你也可以在postman中加上這個session,不過就麻煩很多,我使用get效果一樣的)
最后這里有一篇不錯的關于security前后端分離登錄的文章:https://blog.csdn.net/ycf921244819/article/details/108538506
這里是我分析的security認證過程源碼(有點亂,但最后兩張圖比較清晰),有興趣的可以來看看:
https://blog.csdn.net/qq_42682745/article/details/120713818
原文鏈接:https://blog.csdn.net/qq_42682745/article/details/121326021
相關推薦
- 2022-09-06 C#面向對象編程中接口隔離原則的示例詳解_C#教程
- 2022-06-18 C語言簡明講解單引號與雙引號的使用_C 語言
- 2022-04-09 iOS實現簡單計算器小功能_IOS
- 2022-09-10 Oracle數據泵實現不同用戶導入導出表級_oracle
- 2022-09-05 用兩個隊列模擬一個棧
- 2023-01-01 MongoDB?Shell常用基本操作命令詳解_MongoDB
- 2022-11-16 Python數據分析之matplotlib繪圖詳解_python
- 2022-11-02 Python封裝解構以及丟棄變量_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支