Spring?boot框架JWT實現(xiàn)用戶賬戶密碼登錄驗證流程
1、JWT定義
JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)應(yīng)用間傳遞信息的安全傳輸方式。它是一種緊湊且自包含的方式,通過使用數(shù)字簽名來驗證數(shù)據(jù)的完整性和真實性。
JWT由三部分組成,使用.進行分隔:
- Header(頭部):包含JWT的類型(typ)和使用的簽名算法(alg)等信息。
- Payload(負載):包含要傳輸?shù)臄?shù)據(jù),例如用戶身份信息、權(quán)限等。它是JWT的主要內(nèi)容,可以自定義添加其他需要的字段。
- Signature(簽名):使用指定的算法對Header和Payload進行簽名,以確保數(shù)據(jù)在傳輸過程中沒有被篡改。
1、1 JWT工作流程
- 用戶使用有效的身份憑證(如用戶名和密碼)向服務(wù)器發(fā)送登錄請求。
- 服務(wù)器驗證用戶身份信息,如果驗證通過,生成一個JWT并將其返回給客戶端。
- 客戶端在后續(xù)的請求中將JWT添加到請求的頭部、查詢參數(shù)或Cookie中進行傳遞。
- 服務(wù)器接收到請求后,使用密鑰驗證JWT的簽名和完整性,并從中提取出有效的用戶信息和權(quán)限等數(shù)據(jù)進行處理。
- 如果JWT驗證通過,服務(wù)器處理請求并返回響應(yīng)給客戶端。
1、2 JWT優(yōu)點
優(yōu)點包括:
- 簡單:JWT使用JSON格式存儲信息,易于理解和使用。
- 自包含:JWT中攜帶了用戶的信息和權(quán)限等數(shù)據(jù),避免了頻繁查詢數(shù)據(jù)庫的開銷。
- 可擴展:JWT的負載部分可以自定義添加需要的字段。
- 跨平臺和語言支持:JWT在各種平臺和編程語言中都有對應(yīng)的實現(xiàn)和支持。
- 無狀態(tài):JWT本身是無狀態(tài)的,服務(wù)器不需要保存用戶的會話信息,提高了可伸縮性。
2、添加依賴項到pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
3、創(chuàng)建用戶實體類
創(chuàng)建一個表示用戶的實體類,例如User,其中包含用戶名和密碼等屬性。
如下:

4、實現(xiàn)認證服務(wù)
創(chuàng)建一個類實現(xiàn)Spring Security的UserDetailsService接口,用于加載用戶信息。在該類中,根據(jù)用戶名查詢數(shù)據(jù)庫,獲取用戶信息,包括密碼。
public List<UserEntity> findAllService() {
return userMapper.findAllUser();
}
public ResultResponse login(String name,String password) {
UserEntity user=userMapper.checkPassword(name,password);
if(user != null){
//不等于null就開始頒發(fā)jwt
String token = jwtUtils.generateToken(name);
System.out.println(token);
return ResultResponse.returnToken(ResultResponse.success("頒發(fā)token成功",token));
}
return ResultResponse.illegalToken();
}
public ResultResponse info(String token) {
String tokenString = token;
String subject = JwtUtils.getSubject(tokenString);
UserDTO userinfo=userMapper.getUserByUsername(subject);
int status=userinfo.getStatus();
if(status==1){
String role=userinfo.getRoleName();
Map<String, Object> map = new HashMap<>();
String[] roles = {role};
map.put("name", userinfo.getName());
map.put("avatar", userinfo.getAvatar());
map.put("roles", roles);
return ResultResponse.returnToken(ResultResponse.success("用戶信息獲取成功",map));
}
return ResultResponse.returnToken(ResultResponse.fail("用戶已經(jīng)被禁用",userinfo));
}5、登錄請求處理
創(chuàng)建一個登錄請求處理的Controller,用于處理用戶登錄請求。在該Controller中,接收用戶名和密碼參數(shù),并進行認證。
@CrossOrigin
@PostMapping("/user/login")
public ResultResponse login(@RequestBody UserEntity user) {
String username = user.getUsername();
String password = user.getPassword();
// 生成JWT并返回給客戶端,用戶名和密碼正確就生成jwt
return userService.login(username,password);
}6、生成JWT
在認證成功后,使用JJWT庫生成JWT,并將JWT作為響應(yīng)返回給客戶端.
@Component
public class InterceptorConfig implements WebMvcConfigurer {
private JdbcTemplate jdbcTemplate;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
//給前端輸出json的方法
private void returnJson(HttpServletResponse response, String json) throws Exception{
PrintWriter writer = null;
try {
writer = response.getWriter();
writer.write(json);
} catch (IOException e) {
} finally {
if (writer != null)
writer.close();
}
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("已經(jīng)進入攔截器");
// 設(shè)置跨域訪問的響應(yīng)頭信息
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Token");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
// 獲取tokenHeader
String tokenHeader = request.getHeader("x-token");
System.out.println("前端傳入X-Token是============="+tokenHeader);
// 進行token合法性驗證
if(!JwtUtils.validateToken(tokenHeader)){
String jsonString = JSON.toJSONString(ResultResponse.illegalToken());
returnJson(response,jsonString);
System.out.println("未放行?。?!");
return false;
}
// 鑒權(quán)操作
String path = request.getRequestURI();
String sub = JwtUtils.getSubject(tokenHeader);
System.out.println(path);
// 從數(shù)據(jù)庫中查詢用戶角色id
Integer roleId = jdbcTemplate.queryForObject("SELECT role FROM tskj_user WHERE name = ?", Integer.class, sub);
String targets = jdbcTemplate.queryForObject("SELECT targets FROM tskj_role WHERE id = ?", String.class, roleId);
String tarid = jdbcTemplate.queryForObject("SELECT id FROM tskj_target WHERE target = ? and status=1", String.class, path);
if (targets.contains(tarid)) {
System.out.println("擁有此節(jié)點權(quán)限:"+path);
} else {
String jsonString = JSON.toJSONString(ResultResponse.illegalToken());
returnJson(response,jsonString);
System.out.println("不擁有此節(jié)點權(quán)限:"+path);
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// System.out.println("請求處理完畢,但還沒有進行視圖渲染");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// System.out.println("整個請求處理完成,視圖已渲染完畢");
}
}).addPathPatterns("/**/*").excludePathPatterns("/tskj/user/login","/static/*","/tskj/setting/getSetData","/tskj/user/logout");
System.out.println("攔截器已經(jīng)初始化并添加成功");
WebMvcConfigurer.super.addInterceptors(registry);
}
public InterceptorConfig(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}以上步驟是一個基本的實現(xiàn)流程。
到此這篇關(guān)于Spring boot框架 JWT實現(xiàn)用戶賬戶密碼登錄驗證的文章就介紹到這了,更多相關(guān)Spring boot JWT用戶登錄驗證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用Redis對用戶IP進行接口限流的項目實踐
本文主要介紹了SpringBoot使用Redis對用戶IP進行接口限流,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07
java如何動態(tài)執(zhí)行while循環(huán)
這篇文章主要介紹了java如何動態(tài)執(zhí)行while循環(huán)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
MyBatis-Plus數(shù)據(jù)庫配置與數(shù)據(jù)源整合方案
本文詳細介紹了在MyBatis-Plus中進行數(shù)據(jù)庫配置與數(shù)據(jù)源整合的常見方法,包括單數(shù)據(jù)源和多數(shù)據(jù)源的配置步驟,以及如何使用SpringBoot的自動配置和手動配置來管理數(shù)據(jù)源,通過合理的配置,開發(fā)者可以簡化數(shù)據(jù)庫操作,實現(xiàn)高效的數(shù)據(jù)庫管理和復雜的應(yīng)用架構(gòu)2025-02-02
解決SpringBoot項目讀取yml文件中值為中文時,在視圖頁面顯示亂碼
這篇文章主要介紹了解決SpringBoot項目讀取yml文件中值為中文時,在視圖頁面顯示亂碼的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Mybatis foreach標簽使用不當導致異常的原因淺析
這篇文章主要介紹了Mybatis foreach標簽使用不當導致異常的原因探究,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-12-12
Java編程中實現(xiàn)Condition控制線程通信
這篇文章主要介紹了Java編程中實現(xiàn)Condition控制線程通信,簡單介紹了Java中控制線程通信的方法,以及對condition的解析和實例,具有一定參考價值,需要的朋友可以了解下。2017-11-11
Java super關(guān)鍵字用法實戰(zhàn)案例分析
這篇文章主要介紹了Java super關(guān)鍵字用法,結(jié)合具體案例形式分析了java super關(guān)鍵字調(diào)用父類構(gòu)造方法、屬性及方法等相關(guān)操作技巧與注意事項,需要的朋友可以參考下2019-09-09
深入理解Java中Filter的作用種類及應(yīng)用場景
Filter(過濾器)是Java Web中的一種重要組件,可以對請求和響應(yīng)進行攔截處理,對數(shù)據(jù)進行過濾和處理。Filter可以實現(xiàn)許多功能,如:鑒權(quán)、日志記錄、字符編碼轉(zhuǎn)換、數(shù)據(jù)壓縮、請求重定向等等2023-04-04

