網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
根據(jù)上篇的實(shí)現(xiàn)思想,現(xiàn)在我們正式實(shí)現(xiàn)下內(nèi)容。
需要實(shí)現(xiàn)的內(nèi)容(基于之前的實(shí)現(xiàn)SpringSecurity 架子):
1.? 修改 JwtAuthenticationSuccessHandler ,需要將上下文信息存入redis:
? ? ? 因?yàn)轵?yàn)證環(huán)節(jié)需要實(shí)現(xiàn)從redis獲取上下文,設(shè)置為SecurityContextHolder。
2. 自定義實(shí)現(xiàn)JwtAuthorFilter,攔截所有請(qǐng)求,對(duì)token進(jìn)行驗(yàn)證,驗(yàn)證內(nèi)容:是否攜帶token,是? ? ? 否有效等(根據(jù)需求實(shí)現(xiàn)):進(jìn)行token驗(yàn)證,無效token或者無token將直接進(jìn)入后續(xù)過濾器? ? ? ? ? 中,但是將無法獲取SecurityContextHolder上下文內(nèi)容,在關(guān)閉session管理的情況下,授權(quán)認(rèn)? ? ? 證失敗。
3.?JwtAuthorFilter加入過濾鏈。
實(shí)現(xiàn):
1. 修改?JwtAuthenticationSuccessHandler
/**
* @Author: 一只會(huì)飛的豬
* @Date: 2021/9/11 18:50
* @Version 1.0
* springsecurity 自定義認(rèn)證成功handler
**/
@Component
public class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private static final String REDIS_KEY = "USER_LOGIN:";
@Autowired
RedisCache redisCache;
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
try {
Map<String,Object> map = new HashMap <>( );
httpServletResponse.setContentType("application/json;charset=utf-8");
LoginUser user = (LoginUser) authentication.getPrincipal();
SysUser sysUser = user.getUserInfo();
// 將當(dāng)前用戶信息存入redis,key為 REDIS_KEY + userid 記錄用戶登錄情況,以及后續(xù)驗(yàn)證失效時(shí)間5分鐘
redisCache.setCacheObject( REDIS_KEY+sysUser.getId(),user,300, TimeUnit.SECONDS);
String token = JwtTokenUtils.createToken( String.valueOf( sysUser.getId() ), false );
map.put( "token",token );
map.put( "userinfo",sysUser );
map.put( "code",200 );
httpServletResponse.getWriter().write(JSONObject.toJSONString(map));
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. 自定義實(shí)現(xiàn)JwtAuthorFilter
/**
* @Author: 一只會(huì)飛的豬
* @Date: 2021/9/14 10:07
* @Version 1.0
**/
@Component
public class JwtAuthorFilter extends OncePerRequestFilter {
private static final String REDIS_KEY = "USER_LOGIN:";
@Autowired
RedisCache redisCache;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
try {
// 獲取請(qǐng)求頭傳遞過來的token數(shù)據(jù)
String token = TokenUtils.getToken( httpServletRequest );
if (token != null && !"".equals( token )) {
// 驗(yàn)證token是否有效
boolean expiration = JwtTokenUtils.isExpiration( token );
if(expiration){
// 過期了,攔截訪問
filterChain.doFilter( httpServletRequest, httpServletResponse );
return;
}
String userId = JwtTokenUtils.getUserID( token );
// 通過userID獲取redis中的緩存信息
LoginUser loginUser = redisCache.getCacheObject( REDIS_KEY + userId );
if (loginUser != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// 刷新令牌
redisCache.setCacheObject(REDIS_KEY + userId, loginUser, 300, TimeUnit.SECONDS);
// 將從redis獲取到的用戶信息set到上下文中
LoginJwtToken loginJwtToken = new LoginJwtToken( loginUser.getAuthorities(), loginUser, loginUser.getPassword() );
loginJwtToken.setDetails( new WebAuthenticationDetailsSource().buildDetails( httpServletRequest ) );
SecurityContextHolder.getContext().setAuthentication( loginJwtToken );
}
}
}catch (MalformedJwtException e){
filterChain.doFilter( httpServletRequest, httpServletResponse );
return;
}
// 如果token為空直接下一步過濾器,此時(shí)上線文中無用戶信息,所有在后續(xù)認(rèn)證環(huán)節(jié)失敗
filterChain.doFilter( httpServletRequest, httpServletResponse );
}
}
3.?JwtAuthorFilter加入過濾鏈
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
// 關(guān)閉security session管理,意味著用戶認(rèn)證之后信息不會(huì)存儲(chǔ)到session中,下面自定義了token過濾器處理,使用redis實(shí)現(xiàn)緩存
http.sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS );
http.authorizeRequests().antMatchers( "/**/test" ).permitAll();
http.authorizeRequests().antMatchers( "/**/login" ).permitAll()
.antMatchers( "/system/user/list" ).authenticated();
// 設(shè)置用于認(rèn)證的管理器
jwtLoginFilter.setAuthenticationManager( this.authenticationManagerBean() );
// 自定義的認(rèn)證過濾器加入filter鏈
http.addFilterAt( jwtLoginFilter,UsernamePasswordAuthenticationFilter.class );
// 自定義認(rèn)證成功Handler加入過濾器
jwtLoginFilter.setAuthenticationSuccessHandler( jwtAuthenticationSuccessHandler );
// 自定義認(rèn)證失敗Handler加入過濾器
jwtLoginFilter.setAuthenticationFailureHandler( jwtAuthenticationFailureHandler );
// 自定義的Provider 加入認(rèn)證管理器
http.authenticationProvider( jwtAuthProvider );
// 自定義驗(yàn)證失敗點(diǎn)
http.exceptionHandling().authenticationEntryPoint( myAuthenticationEntryPoint );
// 加入token驗(yàn)證過濾器
http.addFilterBefore( jwtAuthorFilter,JwtLoginFilter.class );
}
結(jié)果截圖:
不適用token,或者失效:
正常使用token:
?
?springsecurity 提供的了完善的過濾鏈來處理認(rèn)證和授權(quán),保障服務(wù)安全。針對(duì)不同企業(yè)不同需要,其同樣也有高擴(kuò)展性,完全可以根據(jù)各自企業(yè)的需求實(shí)現(xiàn)需要的拓展內(nèi)容。 比如基于OAuth2的SSO單點(diǎn)登錄的實(shí)現(xiàn)等等。
原文鏈接:https://blog.csdn.net/qq_31142237/article/details/120311067
相關(guān)推薦
- 2022-10-31 .Net中的Http請(qǐng)求調(diào)用詳解(Post與Get)_實(shí)用技巧
- 2022-05-25 springboot整合jpa報(bào)錯(cuò)詳解
- 2022-12-02 C語(yǔ)言實(shí)現(xiàn)三子棋小游戲的示例代碼_C 語(yǔ)言
- 2022-10-04 C++兩種素?cái)?shù)判定方法_C 語(yǔ)言
- 2022-06-11 Python語(yǔ)法學(xué)習(xí)之進(jìn)程池與進(jìn)程鎖詳解_python
- 2022-05-31 詳解python學(xué)習(xí)筆記之解釋器_python
- 2022-06-19 python繪制散點(diǎn)圖和折線圖的方法_python
- 2024-03-18 bootstrap application 和 nacos 中配置文件的優(yōu)先級(jí)
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支