Spring?boot框架JWT實(shí)現(xiàn)用戶(hù)賬戶(hù)密碼登錄驗(yàn)證流程
1、JWT定義
JWT(JSON Web Token)是一種用于在網(wǎng)絡(luò)應(yīng)用間傳遞信息的安全傳輸方式。它是一種緊湊且自包含的方式,通過(guò)使用數(shù)字簽名來(lái)驗(yàn)證數(shù)據(jù)的完整性和真實(shí)性。
JWT由三部分組成,使用.
進(jìn)行分隔:
- Header(頭部):包含JWT的類(lèi)型(typ)和使用的簽名算法(alg)等信息。
- Payload(負(fù)載):包含要傳輸?shù)臄?shù)據(jù),例如用戶(hù)身份信息、權(quán)限等。它是JWT的主要內(nèi)容,可以自定義添加其他需要的字段。
- Signature(簽名):使用指定的算法對(duì)Header和Payload進(jìn)行簽名,以確保數(shù)據(jù)在傳輸過(guò)程中沒(méi)有被篡改。
1、1 JWT工作流程
- 用戶(hù)使用有效的身份憑證(如用戶(hù)名和密碼)向服務(wù)器發(fā)送登錄請(qǐng)求。
- 服務(wù)器驗(yàn)證用戶(hù)身份信息,如果驗(yàn)證通過(guò),生成一個(gè)JWT并將其返回給客戶(hù)端。
- 客戶(hù)端在后續(xù)的請(qǐng)求中將JWT添加到請(qǐng)求的頭部、查詢(xún)參數(shù)或Cookie中進(jìn)行傳遞。
- 服務(wù)器接收到請(qǐng)求后,使用密鑰驗(yàn)證JWT的簽名和完整性,并從中提取出有效的用戶(hù)信息和權(quán)限等數(shù)據(jù)進(jìn)行處理。
- 如果JWT驗(yàn)證通過(guò),服務(wù)器處理請(qǐng)求并返回響應(yīng)給客戶(hù)端。
1、2 JWT優(yōu)點(diǎn)
優(yōu)點(diǎn)包括:
- 簡(jiǎn)單:JWT使用JSON格式存儲(chǔ)信息,易于理解和使用。
- 自包含:JWT中攜帶了用戶(hù)的信息和權(quán)限等數(shù)據(jù),避免了頻繁查詢(xún)數(shù)據(jù)庫(kù)的開(kāi)銷(xiāo)。
- 可擴(kuò)展:JWT的負(fù)載部分可以自定義添加需要的字段。
- 跨平臺(tái)和語(yǔ)言支持:JWT在各種平臺(tái)和編程語(yǔ)言中都有對(duì)應(yīng)的實(shí)現(xiàn)和支持。
- 無(wú)狀態(tài):JWT本身是無(wú)狀態(tài)的,服務(wù)器不需要保存用戶(hù)的會(huì)話(huà)信息,提高了可伸縮性。
2、添加依賴(lài)項(xiàng)到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)建用戶(hù)實(shí)體類(lèi)
創(chuàng)建一個(gè)表示用戶(hù)的實(shí)體類(lèi),例如User
,其中包含用戶(hù)名和密碼等屬性。
如下:
4、實(shí)現(xiàn)認(rèn)證服務(wù)
創(chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)Spring Security的UserDetailsService
接口,用于加載用戶(hù)信息。在該類(lèi)中,根據(jù)用戶(hù)名查詢(xún)數(shù)據(jù)庫(kù),獲取用戶(hù)信息,包括密碼。
public List<UserEntity> findAllService() { return userMapper.findAllUser(); } public ResultResponse login(String name,String password) { UserEntity user=userMapper.checkPassword(name,password); if(user != null){ //不等于null就開(kāi)始頒發(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("用戶(hù)信息獲取成功",map)); } return ResultResponse.returnToken(ResultResponse.fail("用戶(hù)已經(jīng)被禁用",userinfo)); }
5、登錄請(qǐng)求處理
創(chuàng)建一個(gè)登錄請(qǐng)求處理的Controller,用于處理用戶(hù)登錄請(qǐng)求。在該Controller中,接收用戶(hù)名和密碼參數(shù),并進(jìn)行認(rèn)證。
@CrossOrigin @PostMapping("/user/login") public ResultResponse login(@RequestBody UserEntity user) { String username = user.getUsername(); String password = user.getPassword(); // 生成JWT并返回給客戶(hù)端,用戶(hù)名和密碼正確就生成jwt return userService.login(username,password); }
6、生成JWT
在認(rèn)證成功后,使用JJWT庫(kù)生成JWT,并將JWT作為響應(yīng)返回給客戶(hù)端.
@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)進(jìn)入攔截器"); // 設(shè)置跨域訪(fǎng)問(wèn)的響應(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); // 進(jìn)行token合法性驗(yàn)證 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ù)庫(kù)中查詢(xún)用戶(hù)角色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é)點(diǎn)權(quán)限:"+path); } else { String jsonString = JSON.toJSONString(ResultResponse.illegalToken()); returnJson(response,jsonString); System.out.println("不擁有此節(jié)點(diǎn)權(quán)限:"+path); return false; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // System.out.println("請(qǐng)求處理完畢,但還沒(méi)有進(jìn)行視圖渲染"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // System.out.println("整個(gè)請(qǐng)求處理完成,視圖已渲染完畢"); } }).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; } }
以上步驟是一個(gè)基本的實(shí)現(xiàn)流程。
到此這篇關(guān)于Spring boot框架 JWT實(shí)現(xiàn)用戶(hù)賬戶(hù)密碼登錄驗(yàn)證的文章就介紹到這了,更多相關(guān)Spring boot JWT用戶(hù)登錄驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用Redis對(duì)用戶(hù)IP進(jìn)行接口限流的項(xiàng)目實(shí)踐
本文主要介紹了SpringBoot使用Redis對(duì)用戶(hù)IP進(jìn)行接口限流,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07java如何動(dòng)態(tài)執(zhí)行while循環(huán)
這篇文章主要介紹了java如何動(dòng)態(tài)執(zhí)行while循環(huán)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01MyBatis-Plus數(shù)據(jù)庫(kù)配置與數(shù)據(jù)源整合方案
本文詳細(xì)介紹了在MyBatis-Plus中進(jìn)行數(shù)據(jù)庫(kù)配置與數(shù)據(jù)源整合的常見(jiàn)方法,包括單數(shù)據(jù)源和多數(shù)據(jù)源的配置步驟,以及如何使用SpringBoot的自動(dòng)配置和手動(dòng)配置來(lái)管理數(shù)據(jù)源,通過(guò)合理的配置,開(kāi)發(fā)者可以簡(jiǎn)化數(shù)據(jù)庫(kù)操作,實(shí)現(xiàn)高效的數(shù)據(jù)庫(kù)管理和復(fù)雜的應(yīng)用架構(gòu)2025-02-02解決SpringBoot項(xiàng)目讀取yml文件中值為中文時(shí),在視圖頁(yè)面顯示亂碼
這篇文章主要介紹了解決SpringBoot項(xiàng)目讀取yml文件中值為中文時(shí),在視圖頁(yè)面顯示亂碼的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Mybatis foreach標(biāo)簽使用不當(dāng)導(dǎo)致異常的原因淺析
這篇文章主要介紹了Mybatis foreach標(biāo)簽使用不當(dāng)導(dǎo)致異常的原因探究,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12Java編程中實(shí)現(xiàn)Condition控制線(xiàn)程通信
這篇文章主要介紹了Java編程中實(shí)現(xiàn)Condition控制線(xiàn)程通信,簡(jiǎn)單介紹了Java中控制線(xiàn)程通信的方法,以及對(duì)condition的解析和實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11Java super關(guān)鍵字用法實(shí)戰(zhàn)案例分析
這篇文章主要介紹了Java super關(guān)鍵字用法,結(jié)合具體案例形式分析了java super關(guān)鍵字調(diào)用父類(lèi)構(gòu)造方法、屬性及方法等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-09-09深入理解Java中Filter的作用種類(lèi)及應(yīng)用場(chǎng)景
Filter(過(guò)濾器)是Java Web中的一種重要組件,可以對(duì)請(qǐng)求和響應(yīng)進(jìn)行攔截處理,對(duì)數(shù)據(jù)進(jìn)行過(guò)濾和處理。Filter可以實(shí)現(xiàn)許多功能,如:鑒權(quán)、日志記錄、字符編碼轉(zhuǎn)換、數(shù)據(jù)壓縮、請(qǐng)求重定向等等2023-04-04