網站首頁 編程語言 正文
一言以蔽之,JWT 可以攜帶非敏感信息,并具有不可篡改性。可以通過驗證是否被篡改,以及讀取信息內容,完成網絡認證的三個問題:“你是誰”、“你有哪些權限”、“是不是冒充的”。??
為了安全,使用它需要采用 Https 協議,并且一定要小心防止用于加密的密鑰泄露。
采用 JWT 的認證方式下,服務端并不存儲用戶狀態信息,有效期內無法廢棄,有效期到期后,需要重新創建一個新的來替換。?
所以它并不適合做長期狀態保持,不適合需要用戶踢下線的場景,不適合需要頻繁修改用戶信息的場景。因為要解決這些問題,總是需要額外查詢數據庫或者緩存,或者反復加密解密,強扭的瓜不甜,不如直接使用 Session。不過作為服務間的短時效切換,還是非常合適的,就比如 OAuth 之類的。
目標功能點
-
通過填寫用戶名和密碼登錄。
- 驗證成功后, 服務端生成 JWT 認證 token, 并返回給客戶端。
- 驗證失敗后返回錯誤信息。
- 客戶端在每次請求中攜帶 JWT 來訪問權限內的接口。
- 每次請求驗證 token 有效性和權限,在無有效 token 時拋出 401 未授權錯誤。
- 當發現請求帶著的 token 有效期快到了的時候,返回特定狀態碼,重新請求一個新 token。
-
???????Spring Security是Spring家族中的安全框架,可以用來做用戶驗證和權限管理等。Spring Security是一款重型框架,不過功能十分強大。一般來說,如果項目中需要進行權限管理,具有多個角色和多種權限,我們可以使用Spring Security。SpringSecurity 采用的是責任鏈的設計模式,是一堆過濾器鏈的組合,它有一條很長的過濾器鏈。
準備工作
引入 Maven 依賴
針對這個登錄驗證的實現,需要引入 Spring Security、jackson、java-jwt 三個包。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.12.1</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.12.1</version> </dependency>
配置 DAO 數據層
要驗證用戶前,自然是先要創建用戶實體對象,以及獲取用戶的服務類。不同的是,這兩個類需要實現 Spring Security 的接口,以便將它們集成到驗證框架中。
User
用戶實體類需要實現 ”UserDetails“ 接口,這個接口要求實現?getUsername
、getPassword
、getAuthorities
?三個方法,用以獲取用戶名、密碼和權限。以及?isAccountNonExpired
`isAccountNonLocked
、isCredentialsNonExpired
、isEnabled
?這四個判斷是否是有效用戶的方法,因為和驗證無關,所以先都返回?true
。這里圖方便,用了?lombok
。
@Data public class User implements UserDetails { private static final long serialVersionUID = 1L; private String username; private String password; private Collection<? extends GrantedAuthority> authorities; ... }
UserService
用戶服務類需要實現 “UserDetailsService” 接口,這個接口非常簡單,只需要實現?loadUserByUsername(String username)
?這么一個方法。這里使用了 MyBatis 來連接數據庫獲取用戶信息。
@Service public class UserService implements UserDetailsService { @Autowired UserMapper userMapper; @Override @Transactional public User loadUserByUsername(String username) { return userMapper.getByUsername(username); } ... }
創建 JWT 工具類
這個工具類主要負責 token 的生成,驗證,從中取值。
@Component public class JwtTokenProvider { private static final long JWT_EXPIRATION = 5 * 60 * 1000L; // 五分鐘過期 public static final String TOKEN_PREFIX = "Bearer "; // token 的開頭字符串 private String jwtSecret = "XXX 密鑰,打死也不能告訴別人"; ... }
生成 JWT:從以通過驗證的認證對象中,獲取用戶信息,然后用指定加密方式,以及過期時間生成 token。這里簡單的只加了用戶名這一個信息到 token 中:
public String generateToken(Authentication authentication) { User userPrincipal = (User) authentication.getPrincipal(); // 獲取用戶對象 Date expireDate = new Date(System.currentTimeMillis() + JWT_EXPIRATION); // 設置過期時間 try { Algorithm algorithm = Algorithm.HMAC256(jwtSecret); // 指定加密方式 return JWT.create().withExpiresAt(expireDate).withClaim("username", userPrincipal.getUsername()) .sign(algorithm); // 簽發 JWT } catch (JWTCreationException jwtCreationException) { return null; } }
驗證 JWT:指定和簽發相同的加密方式,驗證這個 token 是否是本服務器簽發,是否篡改,或者已過期。
public boolean validateToken(String authToken) { try { Algorithm algorithm = Algorithm.HMAC256(jwtSecret); // 和簽發保持一致 JWTVerifier verifier = JWT.require(algorithm).build(); verifier.verify(authToken); return true; } catch (JWTVerificationException jwtVerificationException) { return false; } }
獲取荷載信息:從 token 的荷載部分里解析用戶名信息,這部分是 md5 編碼的,屬于公開信息。
public String getUsernameFromJWT(String authToken) { try { DecodedJWT jwt = JWT.decode(authToken); return jwt.getClaim("username").asString(); } catch (JWTDecodeException jwtDecodeException) { return null; } }
登錄
登錄部分需要創建三個文件:負責登錄接口處理的攔截器,登陸成功或者失敗的處理類。
LoginFilter
Spring Security 默認自帶表單登錄,負責處理這個登錄驗證過程的過濾器叫“UsernamePasswordAuthenticationFilter”,不過它只支持表單傳值,這里用自定義的類繼承它,使其能夠支持 JSON 傳值,負責登錄驗證接口。
這個攔截器只需要負責從請求中取值即可,驗證工作 Spring Security 會幫我們處理好。
滑動驗證頁面
SpringBoot整合Spring Security + JWT實現用戶認證-阿里云開發者社區?
原文鏈接:https://blog.csdn.net/zdwzzu2006/article/details/131742698
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-01-31 (數據)圖像預處理——image augmentation圖像增廣之cutout、Mixup、Cut
- 2022-10-22 PyTorch中的CUDA的操作方法_python
- 2022-10-12 Android自定義View實現遙控器按鈕_Android
- 2022-06-06 淺談Redis?中的過期刪除策略和內存淘汰機制_Redis
- 2023-01-05 Kotlin?高階函數與Lambda表達式示例詳解_Android
- 2022-09-13 教你一招完美解決vscode安裝go插件失敗問題_Golang
- 2023-12-07 redis key
- 2022-05-14 .NetCore?Web?Api?利用ActionFilterAttribute統一接口返回值格式及
- 欄目分類
-
- 最近更新
-
- 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同步修改后的遠程分支