【wiki知識庫】08.添加用戶登錄功能--后端SpringBoot部分

目錄

一、今日目標?

二、SpringBoot后端實現

2.1 新增UserLoginParam

2.2 修改UserController

2.3 UserServiceImpl代碼

2.4 創建用戶上下文工具類

2.5?通過token校驗用戶(重要)

2.6 創建WebMvcConfig

2.7 用戶權限校驗攔截器


一、今日目標

上篇文章鏈接:【wiki知識庫】08.添加用戶登錄功能–前端Vue部分修改-CSDN博客

這篇文章主要是實現一下用戶登錄功能的后端部分,登錄功能需要使用redis,不懂redis可以看我之前的一篇文章。

Redis文章鏈接:【Spring】SpringBoot整合Redis,用Redis實現限流(附Redis解壓包)_springboot 限流 redis-CSDN博客

那么為什么要用到Redis呢?

這個問題關系到整個系統的用戶校驗,當我們登錄成功的時候,后端會生成一個用于用戶校驗的token值,然后把這個值傳給前端,每次用戶請求后端的時候都要帶上這個token值,這個token的值當中記錄了當前登錄的用戶是誰,還有過期時間等信息,這樣子就可以防止那些沒有登陸的用戶去直接訪問我們的后端調用接口。所以這個token還是需要妥善保管的,一旦token丟失別人就可能用你的token去發送請求,修改你的數據。

二、SpringBoot后端實現

2.1 新增UserLoginParam

這里也做了校驗,其實這個事情完全可以放到前端實現,但是也要考慮到有直接調用接口的情況,這時也要給出錯誤提示。

@Data
public class UserLoginParam {@NotEmpty(message = "【用戶名】不能為空")private String loginName;@NotEmpty(message = "【密碼】不能為空")@Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,32}$", message = "【密碼】規則不正確")private String password;}

2.2 修改UserController

直接上代碼吧。這里拿到了用戶的賬號和用戶的密碼,然后判斷加密后的密碼和數據庫中取出來的用戶密碼是否相同,如果相同那么就可以登陸。登陸后通過工具類生成一個不會重復的Long類型的值作為該用戶的token,然后以token為key,登錄用戶創建的對象作為值,保存到redis當中,以便于后續用戶訪問接口時,通過用戶token來判斷是哪個用戶訪問接口。

  @PostMapping("/login")public CommonResp login(@Valid @RequestBody UserLoginParam req) {req.setPassword(DigestUtils.md5DigestAsHex(req.getPassword().getBytes()));System.out.println(req);UserLoginVo userLoginResp = userService.login(req);Long token = snowFlake.nextId();userLoginResp.setToken(token.toString());redisTemplate.opsForValue().set(token.toString(), JSONObject.toJSONString(userLoginResp), 3600 * 24, TimeUnit.SECONDS);return new CommonResp(true,"登錄成功",userLoginResp);}@GetMapping("/logout/{token}")public CommonResp logout(@PathVariable String token) {boolean res = redisTemplate.delete(token);String message = Boolean.TRUE.equals(res) ? "登出成功":"登出失敗";return new CommonResp(true,message,null);}

2.3 UserServiceImpl代碼

這個代碼沒有什么好說的,就是查找一次數據庫進行賬號密碼的匹配。

public UserLoginVo login(UserLoginParam req) {User userDb = selectByLoginName(req.getLoginName());if (ObjectUtils.isEmpty(userDb)) {// 用戶名不存在throw new RuntimeException("用戶名不存在");} else {if (userDb.getPassword().equals(req.getPassword())) {// 登錄成功UserLoginVo userLoginResp = CopyUtil.copy(userDb, UserLoginVo.class);return userLoginResp;} else {// 密碼不對throw new RuntimeException("密碼錯誤");}}}

2.4 創建用戶上下文工具類

這個工具類用戶用戶登錄后保存當前用戶的上下文。

public class LoginUserContext implements Serializable {private static ThreadLocal<UserLoginVo> user = new ThreadLocal<>();public static UserLoginVo getUser() {return user.get();}public static void setUser(UserLoginVo user) {LoginUserContext.user.set(user);}}

2.5通過token校驗用戶(重要)

校驗用戶token需要使用到攔截器或者過濾器,這里我使用攔截器進行用戶token的校驗。整體的校驗流程如下

以下就是登錄攔截器的代碼,

/*** 攔截器:Spring框架特有的,常用于登錄校驗,權限校驗,請求日志打印*/
@Component
public class LoginInterceptor implements HandlerInterceptor {private static final Logger LOG = LoggerFactory.getLogger(LoginInterceptor.class);@Resourceprivate RedisTemplate redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// OPTIONS請求不做校驗,// 前后端分離的架構, 前端會發一個OPTIONS請求先做預檢, 對預檢請求不做校驗if (request.getMethod().toUpperCase().equals("OPTIONS")) {return true;}String path = request.getRequestURL().toString();LOG.info("接口登錄攔截:,path:{}", path);//獲取header的token參數String token = request.getHeader("token");LOG.info("登錄校驗開始,token:{}", token);if (token == null || token.isEmpty()) {LOG.info("token為空,請求被攔截");response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;}Object object = redisTemplate.opsForValue().get(token);// 證明redis中的用戶信息過期了,需要重新登陸if (object == null) {LOG.warn("token無效,請求被攔截");response.setStatus(HttpStatus.UNAUTHORIZED.value());return false;} else {LOG.info("已登錄:{}", object);LoginUserContext.setUser(JSON.parseObject((String) object, UserLoginVo.class));return true;}}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

接下來要把這個攔截器注冊到配置當中。


2.6 創建WebMvcConfig

在config包下創建該類。這個類當中配置了兩個攔截器,一個是登錄攔截器,另一個是用戶權限校驗攔截器。用戶校驗攔截器下邊再說。登錄攔截器只需要部分接口進行攔截就可以了,畢竟有的接口不需要登陸用戶就可以訪問。

有一點值得注意的是,在這個配置類中配置的攔截器的順序會影響校驗結果,校驗的流程是根據你配置的攔截器的順序從上往下校驗的,如果你把攔截器配置寫反了就會出錯。

addInterceptor

注冊一個攔截器

addPathPatterns

該攔截器需要攔截的路徑

excludePathPatterns

該攔截器不需要攔截的路徑

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {@ResourceLoginInterceptor loginInterceptor;@ResourceActionInterceptor actionInterceptor;public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/test/**","/redis/**","/user/login","/user/logout/**","/category/all","/ebook/list","/doc/all/**","/doc/find-content/**",);registry.addInterceptor(actionInterceptor).addPathPatterns("/*/save","/*/delete/**","/*/reset-password");}
}

2.7 用戶權限校驗攔截器

看到下方的代碼你應該知道了用戶上下文的作用,通過用戶上下文拿到用戶的信息來判斷該用戶是否有訪問該接口的權利,我們拒絕非admin用戶外的用戶進行增刪改操作。

但是這種方法有點不太好不知道你們有沒有感覺到,一旦用戶多了之后,如果你想給用戶分配權限,你就要添加很多的用戶在這里。所以一種更好的方式就是RBAC權限校驗,大家可以自己了解一下,也有更好的權限校驗框架SpringSecurity,但是作為一個比較簡單的項目,引入這個框架的學習成本就太大了。

/*** 攔截器:Spring框架特有的,常用于登錄校驗,權限校驗,請求日志打印*/
@Component
public class ActionInterceptor implements HandlerInterceptor {private static final Logger LOG = LoggerFactory.getLogger(ActionInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {// OPTIONS請求不做校驗,// 前后端分離的架構, 前端會發一個OPTIONS請求先做預檢, 對預檢請求不做校驗if ("OPTIONS".equals(request.getMethod().toUpperCase())) {return true;}UserLoginVo userLoginResp = LoginUserContext.getUser();if ("admin".equals(userLoginResp.getLoginName())) {// admin用戶不攔截return true;}LOG.info("操作被攔截");response.setStatus(HttpStatus.OK.value());CommonResp commonResp = new CommonResp(false,"普通用戶暫不開放增刪改操作",null);response.setContentType("application/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");response.getWriter().print(JSONObject.toJSON(commonResp));return false;}}

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

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

相關文章

AI大模型的技術突破與傳媒行業變革

性能與成本&#xff1a;AI大模型的“雙輪驅動” 過去幾年&#xff0c;AI大模型的發展經歷了從實驗室到產業化的關鍵轉折。2025年初&#xff0c;以DeepSeek R1為代表的模型在數學推理、代碼生成等任務中表現超越國際頭部產品&#xff0c;而訓練成本僅為傳統模型的幾十分之一。這…

C++字符串處理指南:從基礎操作到性能優化——基于std::string的全面解析

博主將從C標準庫中的 std::string 出發&#xff0c;詳細探討字符串的處理方法&#xff0c;涵蓋常見操作、性能優化和實際應用場景。以下內容將圍繞std::string 的使用展開&#xff0c;結合代碼示例進行說明。 一、std::string 的基本操作 1.1 創建與初始化 std::string 提供了…

3.【線性代數】——矩陣乘法和逆矩陣

三 矩陣乘法和逆矩陣 1. 矩陣乘法1.1 常規方法1.2 列向量組合1.3 行向量組合1.4 單行和單列的乘積和1.5 塊乘法 2. 逆矩陣2.1 逆矩陣的定義2.2 奇異矩陣2.3 Gauss-Jordan 求逆矩陣2.3.1 求逆矩陣 ? \Longleftrightarrow ?解方程組2.3.2 Gauss-Jordan求逆矩陣 1. 矩陣乘法 1.…

深入了解 Oracle 正則表達式

目錄 深入了解 Oracle 正則表達式一、正則表達式基礎概念二、Oracle 正則表達式語法&#xff08;一&#xff09;字符類&#xff08;二&#xff09;重復限定符&#xff08;三&#xff09;邊界匹配符&#xff08;四&#xff09;分組和捕獲 三、Oracle 正則表達式函數&#xff08;…

用python寫一個聊天室程序

下面是一個簡單的基于Socket的Python聊天室程序示例&#xff0c;包括服務器端和客戶端&#xff1a; 服務器端代碼&#xff1a; import socket import threadingdef handle_client(client, address):print(f"New connection from {address}")while True:msg client…

在nodejs中使用RabbitMQ(六)sharding消息分片

RabbitMQ 的分片插件&#xff08;rabbitmq_sharding&#xff09;允許將消息分布到多個隊列中&#xff0c;這在消息量很大或處理速度要求高的情況下非常有用。分片功能通過將消息拆分到多個隊列中來平衡負載&#xff0c;從而提升消息處理的吞吐量和可靠性。它能夠在多個隊列之間…

1.7 AI智能體實戰指南:從單任務自動化到企業級智能體集群架構

AI智能體實戰指南:從單任務自動化到企業級智能體集群架構 一、智能體技術演進:從腳本工具到認知革命的跨越 1.1 三代智能體能力對比 能力維度第一代(規則驅動)第二代(機器學習)第三代(LLM驅動)任務理解固定模式匹配統計模式識別語義推理與邏輯鏈分解環境適應需人工重寫…

Github 2025-02-14 Java開源項目日報 Top10

根據Github Trendings的統計,今日(2025-02-14統計)共有10個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Java項目10C#項目1Guava: 谷歌Java核心庫 創建周期:3725 天開發語言:Java協議類型:Apache License 2.0Star數量:49867 個Fork數量:10822 次…

C++17中的clamp函數

一、std::clamp() 其實在前面簡單介紹過這個函數&#xff0c;但當時只是一個集中的說明&#xff0c;為了更好的理解std::clamp的應用&#xff0c;本篇再詳細進行闡述一次。std::clamp在C17中其定義的方式為&#xff1a; template< class T > constexpr const T& cl…

WEB安全--SQL注入--常見的注入手段

一、聯表查詢&#xff1a; 1.1原理&#xff1a; 當payload參數被后端查詢語句接收到時&#xff0c;其中的非法語句通過union關聯顯示出其他的數據 1.2示例&#xff1a; #payload: -1 and union select 1,2,database()--#query: $sqlselect * from users where id-1 and union …

QT筆記——QPlainTextEdit

文章目錄 1、概要2、文本設計2.1、設置文本2.1、字體樣式&#xff08;大小、下劃線、加粗、斜體&#xff09; 1、概要 QPlainTextEdit 是 Qt 框架中用于處理純文本編輯的控件&#xff0c;具有輕量級和高效的特點&#xff0c;以下是它常見的應用場景&#xff1a; 文本編輯器&am…

【D2】神經網絡初步學習

總結&#xff1a;學習了 PyTorch 中的基本概念和常用功能&#xff0c;張量&#xff08;Tensor&#xff09;的操作、自動微分&#xff08;Autograd&#xff09;、正向傳播、反向傳播。通過了解認識LeNet 模型&#xff0c;定義神經網絡類&#xff0c;熟悉卷積神經網絡的基本結構和…

DeepSeek處理自有業務的案例:讓AI給你寫一份小眾編輯器(EverEdit)的語法著色文件

1 DeepSeek處理自有業務的案例&#xff1a;讓AI給你寫一份小眾編輯器(EverEdit)的語法著色文件 1.1 背景 AI能力再強&#xff0c;如果不能在企業的自有業務上產生助益&#xff0c;那基本也是一無是處。將企業的自有業務上傳到線上訓練&#xff0c;那是腦子進水的做法&#xff…

DeepSeek教unity------MessagePack-05

動態反序列化 當調用 MessagePackSerializer.Deserialize<object> 或 MessagePackSerializer.Deserialize<dynamic> 時&#xff0c;二進制數據中存在的任何值都將被轉換為基本值&#xff0c;即 bool、char、sbyte、byte、short、int、long、ushort、uint、ulong、…

C++入門之《拷貝構造函數》詳解

拷貝構造函數是構造函數的一個重載 拷貝構造函數是特殊的構造函數&#xff0c;用于基于已存在對象創建新對象。比如定義一個 Person 類&#xff1a; class Person { private:std::string name;int age; public:Person(const std::string& n, int a) : name(n), age(a…

Ollama命令使用指南

Ollama 命令使用指南 Ollama 命令使用指南1. Ollama 命令概覽2. Ollama 命令詳解2.1 啟動 Ollama2.2 創建模型2.3 查看模型信息2.4 運行模型2.5 停止運行的模型2.6 從注冊表拉取模型2.7 推送模型到注冊表2.8 列出本地模型2.9 查看正在運行的模型2.10 復制模型2.11 刪除模型 3. …

為什么配置Redis時候要序列化配置呢

序列化和反序列化&#xff1f;&#xff1a; 序列化&#xff1a;將對象轉換為二進制數據&#xff0c;以便存儲到Redis中。 反序列化&#xff1a;將Redis中的二進制數據轉換回對象&#xff0c;以便在應用程序中使用。 1. 默認序列化器的問題 如果不配置序列化器&#xff0c;Re…

【問】強學如何支持 遷移學習呢?

案例&#xff1a;從CartPole-v1遷移到MountainCar-v0 在源環境&#xff08;CartPole-v1&#xff09;中訓練模型 首先&#xff0c;我們使用DQN算法在CartPole-v1環境中訓練一個強化學習模型。以下是代碼示例&#xff1a; import gym import torch import torch.nn as nn impor…

深入淺出Java反射:掌握動態編程的藝術

小程一言反射何為反射反射核心類反射的基本使用獲取Class對象創建對象調用方法訪問字段 示例程序應用場景優缺點分析優點缺點 注意 再深入一些反射與泛型反射與注解反射與動態代理反射與類加載器 結語 小程一言 本專欄是對Java知識點的總結。在學習Java的過程中&#xff0c;學習…

【算法與數據結構】并查集詳解+題目

目錄 一&#xff0c;什么是并查集 二&#xff0c;并查集的結構 三&#xff0c;并查集的代碼實現 1&#xff0c;并查集的大致結構和初始化 2&#xff0c;find操作 3&#xff0c;Union操作 4&#xff0c;優化 小結&#xff1a; 四&#xff0c;并查集的應用場景 省份…