筆記項目 day02

一、用戶登錄接口

請求參數:

用loginDTO來封裝請求參數,要加上@RequestBody注解

響應參數:

由于data里內容較多,考慮將其封裝到一個LoginUser的實體中,用戶登陸后,需要生成jwtToken并返回給前端。

登錄功能的service層具體實現步驟:

1.根據傳進來的account或email到數據庫里查,查出該用戶的信息。若兩者都不存在,則報錯。

2.校驗用戶的是否存在及密碼是否正確

3.生成jwt令牌。

4.修改最后登陸時間lastLoginAt

代碼如下:

    @Overridepublic Result<LoginVO> login(LoginDTO loginDTO) {User loginUser = null;//1.if(loginDTO.getAccount() == null && loginDTO.getEmail() == null){return ResultUtil.error("請提供用戶名或郵箱!");}if(loginDTO.getAccount() == null && loginDTO.getEmail() != null){loginUser = userMapper.getUserByEmail(loginDTO.getEmail());}if(loginDTO.getEmail() == null && loginDTO.getAccount() != null){loginUser = userMapper.getUserByAccount(loginDTO.getAccount());}//2.if(loginUser == null){return ResultUtil.error("用戶不存在!請注冊!");}if( !loginDTO.getPassword().equals(loginUser.getPassword())){return ResultUtil.error("密碼錯誤!");}//3.String token = jwtUtil.generateToken(loginUser.getUserId());loginUser.setLastLoginAt(LocalDateTime.now());LoginVO loginVO = new LoginVO();BeanUtils.copyProperties(loginUser, loginVO);return Result.success(loginVO , token);}

二、設計jwt工具類

一個jwt工具類應該包含以下幾個功能:

1.生成jwt令牌

流程如下:

其中,claims是載荷,即往jwt令牌里存儲的信息,后續可以通過jwt令牌獲取這些信息。

使用jwts的builder()鏈式生成token,需要指定載荷、簽發時間、過期時間、簽名算法及密鑰secret等信息。

2.從前端傳來的jwt令牌里讀取信息

    public Long getUserIdFromToken(String token) {try{Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();Long userId = (Long) claims.get("userId");return userId;}catch(Exception e){return null;}}

一個天坑:

此處jwt再解析時,claims.get("userID")一定要先轉換成字符串,再轉換成Long,若直接使用(long),由于JWT的聲明(claims)基于JSON標準,JSON不區分整數的具體類型(如IntegerLong)。當數值較小時,某些JWT實現(如JJWT)可能將其解析為Integer,而較大的數值解析為Long,直接強制類型轉換會導致異常。

因此:使用Long.valueOf()來間接轉換。

    public Long getUserIdFromToken(String token) {try {Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();return Long.valueOf(claims.get("userId").toString());} catch (Exception e) {return null;}}

3.校驗jwt令牌是否有效

    //方法3. 檢驗令牌是否有效public boolean validateToken(String token) {try {Jwts.parser().setSigningKey(secret).parseClaimsJws(token);return true;} catch (Exception e) {return false;}}

4.刷新jwt令牌

    public String refreshToken(Long userId) {return generateToken(userId);}

三、獲取當前用戶信息

請求:無,只需攜帶jwt令牌

響應如下:跟LoginUserVo是同樣的

四、如何從請求中獲取jwt令牌?

在第三個需求中,需要先讀取jwt令牌,再從jwt令牌中讀取userID信息。因此,需要從請求中獲取jwt令牌。

這個需求的實現有幾種方案:

1.使用threadlocal來存儲和傳遞

2.使用request.setattribute

3.使用@RequestScope

此處選擇第三種。

實現步驟:

1.定義?@RequestScope?bean,需要加上@Component @RequestScope @Data 這幾個注解。

這個類的作用就是每遇到一個個http請求,就會創建它,我們可以將一些數據存進去,以便后續使用。

創建時機??:每個 HTTP 請求開始時,Spring 會創建一個新的?RequestContext?實例。

??銷毀時機??:請求處理結束后,Spring 自動銷毀該實例

@Data
@RequestScope
@Component
public class RequestContext {public Long userId;public String token;public Boolean isLogin;
}

RequestContext中,isLogin的作用:存儲當前用戶有無登錄,若未登錄,設置成false,只允許其訪問登錄和注冊的服務。

2.在攔截器中注入并設置數據

3.將攔截器注冊到WebConfig中

4. 在 Controller 或 Service 中使用數據??

在需要訪問請求級別數據的組件中,直接注入?RequestContext?Bean。

五、攔截器怎么寫

需求:每當遇到一個請求,就將他攔截下來,并從中讀取jwt 令牌。

具體步驟:

1.定義一個類,它必須實現??HandlerInterceptor ,

2.重寫preHandle這個方法,里面為 是否放行的邏輯

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 對于每個請求進行攔截,獲取請求頭中的 tokenString token = request.getHeader("Authorization");// 然后對 token 進行處理,并將 token 攜帶的信息存儲到,在請求周期中全局存在的 requestScopeData 中//0.token為nullif(token == null){requestContext.setToken(null);requestContext.setUserId(null);requestContext.setIsLogin(false);return true; //不管有沒有登錄,或者jwt令牌合法與否,都放行,后續對這些isLogin為false的請求只開放登陸的權限}token = token.replace("Bearer", "");// 若令牌不合法,requestContext的登錄狀態設置成falseif( ! jwtUtil.validateToken(token)){requestContext.setIsLogin(false);}else{requestContext.setIsLogin(true);requestContext.setToken(token);requestContext.setUserId(jwtUtil.getUserIdFromToken(token));}return true;}

3.配置攔截器

    //配置攔截器@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/error");}
}

六、今日踩坑小結

1.請求體若使用實體類封裝 , 必須加上@RequestBody , 否則后端接受不到前端傳來的數據

2.當前端傳來的參數和方法參數不一致時使用@RequestParam注解,當然,前端傳來多個參數時必須使用

@GetMapping("/user")
public String getUser(@RequestParam("id") Long userId) {// 通過 /user?id=123 訪問時,userId=123return "user";
}

3.@PathVariable

4.@Param注解:mapper層定義的方法,當接受多個參數時,必須使用

// Mapper接口
public interface UserMapper {List<User> findUsersByConditions(@Param("name") String name,@Param("status") Integer status);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/80813.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/80813.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/80813.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025年土木建筑與水利工程國際會議(ICCHE 2025)

2025 International Conference on Civil and Hydraulic Engineering (ICCHE 2025) &#xff08;一&#xff09;會議信息 會議簡稱&#xff1a;ICCHE 2025 大會地點&#xff1a;中國銀川 投稿郵箱&#xff1a;icchesub-paper.com 收錄檢索&#xff1a;提交Ei Compendex,CPCI,C…

運行Spark程序-在shell中運行1

&#xff08;一&#xff09;分布式計算要處理的問題 【老師提問&#xff1a;分布式計算要面臨什么問題&#xff1f;】 【老師總結】 分布式計算需要做到&#xff1a; 1.分區控制。把大的數據拆成一小份一小份的&#xff08;分區&#xff0c;分片&#xff09;讓多臺設備同時計算…

一文理清人工智能,機器學習,深度學習的概念

目錄 一、人工智能的起源與核心范疇&#xff08;1950-1980&#xff09; 1.1 智能機器的最初構想 1.2 核心范疇的初步分化 二、機器學習的興起與技術分化&#xff08;1980-2010&#xff09; 2.1 統計學習的黃金時代 2.2 神經網絡的復興與子集定位 2.3 技術生態的形成與AI…

《Effective Python》第1章 Pythonic 思維總結——編寫優雅、高效的 Python 代碼

《Effective Python》第1章 Pythonic 思維總結——編寫優雅、高效的 Python 代碼 在編程的世界里&#xff0c;每個語言都有其獨特的風格和最佳實踐。對于 Python 而言&#xff0c;“Pythonic”已經成為描述遵循 Python 特定風格的代碼的代名詞。這種風格不僅讓代碼更易讀、更簡…

MySQL 事務(二)

文章目錄 事務隔離性理論理解隔離性隔離級別 事務隔離級別的設置和查看事務隔離級別讀未提交讀提交&#xff08;不可重復讀&#xff09; 事務隔離性理論 理解隔離性 MySQL服務可能會同時被多個客戶端進程(線程)訪問&#xff0c;訪問的方式以事務方式進行一個事務可能由多條SQL…

代碼倉提交分支規范

以下是我部門開發時用的分支規范&#xff0c;參考于Linux社區 Tips 分支命名通常遵循一些最佳實踐和規則&#xff0c;以便使分支的用途和內容清晰易懂&#xff0c;就在寫一個文檔的主題一樣。 功能分支 (Feature Branches) 用于開發新功能。 命名格式&#xff1a;feature/功能名…

Google Earth Engine(GEE) 代碼詳解:批量計算_年 NDVI 并導出(附 Landsat 8 數據處理全流程)

一、代碼整體目標 基于 Landsat 8 衛星數據,批量計算 2013-2020 年研究區的 NDVI(歸一化植被指數),實現去云處理、數據合成、可視化及批量導出為 GeoTIFF 格式,適用于植被動態監測、生態環境評估等場景。 二、代碼分步解析(含核心原理與易錯點) 1. 加載并顯示研究區邊…

Maven 處理依賴沖突

Maven處理依賴沖突 什么是依賴沖突&#xff1f;如何解決&#xff1f;Maven自動處理依賴沖突的規則路徑優先原則第一聲明優先原則注意 子模塊覆蓋父模塊父模塊聲明dependency子模塊覆蓋dependency父模塊聲明dependencyManagement 子模塊覆蓋dependency父模塊聲明dependencyManag…

docker 安裝 sqlserver2022 和注意點

一、前言 1、可以直接參考微軟官方文檔 快速入門&#xff1a;使用 Docker 運行 SQL Server Linux 容器映像&#xff0c;這里主要是說一些注意點和坑 二、安裝 1、拉取鏡像 docker pull mcr.microsoft.com/mssql/server:2022-latest2、創建掛載目錄&#xff0c;這里只是比官方…

Dagster Pipes系列-1:調用外部Python腳本

本文是"Dagster Pipes教程"的第一部分&#xff0c;介紹如何通過Dagster資產調用外部Python腳本并集成到數據管道中。首先&#xff0c;創建Dagster資產subprocess_asset&#xff0c;利用PipesSubprocessClient資源執行外部腳本external_code.py&#xff0c;實現跨進程…

【SQL系列】多表關聯更新

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

C++進階學習:STL常用容器--map/multimap容器

1. map 容器基本概念 map 中所有元素都是 pair pair 中第一個元素為 key &#xff08;鍵值&#xff09; 起到索引運用 第二個元素為 value&#xff08;實值&#xff09; 所有元素都會根據元素的鍵值自動排序 本質&#xff1a; map/multimap 屬于關聯式容器 底層結構是用二…

let,const,var關鍵字的區別

let,const,var關鍵字 let&#xff0c;const&#xff0c;var都存在變量提升 它們都存在變量提升但是稍微有點不同 var變量聲明會被提升到作用域的頂部&#xff0c;并且會被初始化為 undefinedlet 和 const&#xff1a;變量聲明也會被提升到作用域的頂部&#xff0c;但不會被初…

Nuitka 已經不再安全? Nuitka/Cython 打包應用逆向工具 -- pymodhook

pymodhook是一個記錄任意對Python模塊的調用的庫&#xff0c;用于Python逆向分析。 pymodhook庫類似于Android的xposed框架&#xff0c;但不僅能記錄函數的調用參數和返回值&#xff0c;還能記錄模塊的類的任意方法調用&#xff0c;以及任意派生對象的訪問&#xff0c;基于pyob…

path環境變量滿了如何處理,分割 PATH 到 Path1 和 Path2

要正確設置 Path1 的值&#xff0c;你需要將現有的 PATH 環境變量 中的部分路徑復制到 Path1 和 Path2 中。以下是詳細步驟&#xff1a; 步驟 1&#xff1a;獲取當前 PATH 的值 打開環境變量窗口&#xff1a; 按 Win R&#xff0c;輸入 sysdm.cpl&#xff0c;點擊 確定。在 系…

SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理標準)-(一)

1 目的 物料(例如晶圓)加工在設備中的自動化管理與控制是實現工廠自動化的關鍵要素。本標準針對半導體制造環境中與設備內部物料處理相關的通信需求進行了規范。本標準規定了在加工單元接收到的指定材料所應適用的加工方法(例如Etch腔室需要Run哪支Recipe)。它闡述了物料加工的…

【Hadoop】集群搭建實戰:超詳細保姆級教程

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《大數據前沿&#xff1a;技術與應用并進》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、Hadoop簡介 2、Hadoop集群概念 3、 Hadoop 集…

阿里云人工智能大模型通義千問Qwen3開發部署

本文主要描述阿里云人工智能大模型開源社區ModelScope提供的通義千問Qwen3開發部署。 與阿里云一起 輕松實現數智化 讓算力成為公共服務&#xff1a;用大規模的通用計算&#xff0c;幫助客戶做從前不能做的事情&#xff0c;做從前做不到的規模。讓數據成為生產資料&#xff1a;…

24.(vue3.x+vite)引入組件并動態掛載(mount)

示例截圖 組件代碼: <template><div><div>{{message }}</div>

《Python星球日記》 第56天:循環神經網絡(RNN)入門

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 目錄 一、序列數據的特點與挑戰1. 什么是序列數據?2. 序列數據的挑戰二、RNN 的基本結構與前向傳播1. RNN的核心理念2. RNN的數學表達3. RNN的前向傳…