后端技術選型 sa-token校驗學習 下 結合項目學習 前后端登錄

目錄

后端設置

Controller 層

Service 層

后端返回 Token 給前端

1. 用戶提交登錄請求

2. 后端驗證用戶身份

3. 返回 Token

4. 前端保存 Token

前端存儲

1. 前端向后端發起請求

2. 前端存儲一下 Token

3.管理用戶認證的 token 的 工具

4. 在 Service 層進行設置 HTTP 請求工具


后端設置

Controller 層

   /*** 用戶登錄** @param login 登錄參數* @return {@link String} Token*/@ApiOperation(value = "用戶登錄")@PostMapping("/login")public Result<String> login(@Validated @RequestBody LoginReq login) {return Result.success(loginService.login(login));}

Service 層

首先用 userMapper 查詢數據庫中的數據是否存在

          User user = userMapper.selectOne(new LambdaQueryWrapper<User>().select(User::getId).eq(User::getUsername, login.getUsername()).eq(User::getPassword, SecurityUtils.sha256Encrypt(login.getPassword())));

再標記當前登錄賬號 id

// 標記當前會話登錄的賬號id
StpUtil.login(user.getId());

返回 Token 數值

return StpUtil.getTokenValue();

全部代碼

   public String login(LoginReq login) {try {User user = userMapper.selectOne(new LambdaQueryWrapper<User>().select(User::getId).eq(User::getUsername, login.getUsername()).eq(User::getPassword, SecurityUtils.sha256Encrypt(login.getPassword())));Assert.notNull(user, "用戶不存在或密碼錯誤");// 校驗指定賬號是否已被封禁,如果被封禁則拋出異常 `DisableServiceException`StpUtil.checkDisable(user.getId());// 通過校驗后,再進行登錄// 標記當前會話登錄的賬號idStpUtil.login(user.getId());// 拿到當前登錄賬號的IdInteger userId = StpUtil.getLoginIdAsInt();System.out.println("當前登錄賬號的Id: "+userId);String token = StpUtil.getTokenValue();  // 獲取當前線程的 tokenSystem.out.println("Token: " + token);  // 打印出 token 以便調試//            //獲取當前是否登錄
//            StpUtil.isLogin();System.out.println("登錄狀態: "+StpUtil.isLogin());
//            //檢驗當前會話是否已經登錄
//            StpUtil.checkLogin();return StpUtil.getTokenValue();} catch (IllegalArgumentException e) {e.printStackTrace();throw e;}}

后端返回 Token 給前端

后端登錄成功后,通常會將一個 Token 返回給前端,這個 Token 通常是一個 JWT(JSON Web Token),它包含了用戶身份和一些其他的認證信息,并且可以用來進行后續的 API 請求驗證。后端返回 Token 的過程通常是這樣的:

1. 用戶提交登錄請求

用戶輸入用戶名和密碼后,前端會將請求發送到后端,后端會進行認證。

2. 后端驗證用戶身份

后端會根據用戶名和密碼進行身份驗證,如果驗證成功,則生成一個 Token,通常是 JWT 格式。

3. 返回 Token

后端將 Token 返回給前端,前端可以在后續的請求中將這個 Token 放在請求頭中(通常是 Authorization: Bearer token)來進行身份認證。

4. 前端保存 Token

前端通常會把 Token 保存在瀏覽器的 localStoragesessionStorage 中,或者通過 HTTP-only 的 cookie 來存儲,以便在之后的請求中攜帶。

前端存儲

把 表單里面的數據 作為參數

1. 前端向后端發起請求

異步請求

  login(loginForm.value).then(({ data }) => {if (data.flag) {setToken(data.data);// user.GetUserInfo();window.$message?.success("登錄成功");loginForm.value = {username: "",password: "",};app.setLoginFlag(false);}loading.value = false;});

2. 前端存儲一下 Token

    setToken(data.data);

3.管理用戶認證的 token 的 工具

寫一個管理用戶認證的 token 的 TypeScript 代碼

import Cookies from "js-cookie";const TokenKey: string = "Token";// 我網站的域名是www.ttkwsd.top,去前面的www,改成自己的域名
const domain: string = ".gczdy.cn";// token前綴
export let token_prefix = "Bearer ";export function getToken() {return Cookies.get(TokenKey);
}// 本地運行記得刪除domain
export function setToken(token: string) {// 項目線上部署可以取消注釋// return Cookies.set(TokenKey, token, { domain: domain });return Cookies.set(TokenKey, token);
}export function removeToken() {// 項目線上部署可以取消注釋// return Cookies.remove(TokenKey, { domain: domain });return Cookies.remove(TokenKey);
}

這段代碼是用來管理用戶認證的 token(令牌)的,通常用于前端應用中的身份驗證部分。它使用了 js-cookie 庫來處理 cookies 的操作。下面逐行解釋:

1. import Cookies from "js-cookie";

  • 導入 js-cookie 庫,它是一個簡化操作 cookies 的 JavaScript 庫。通過它可以方便地存儲、獲取和刪除 cookies。

2. const TokenKey: string = "Token";

  • 定義了一個常量 TokenKey,值為 "Token",作為存儲 token 的 cookie 鍵名。這個鍵用于在 cookies 中存取用戶的 token。

3. const domain: string = ".gczdy.cn";

  • 定義了一個 domain 常量,表示 cookies 適用的域名。.gczdy.cn 是設置 cookies 時的域名,意味著該 cookie 會對該域及其子域名(例如 www.gczdy.cnapp.gczdy.cn)有效。
  • 代碼中也有注釋提到:如果是本地開發環境,可以刪除該行。

4. export let token_prefix = "Bearer ";

  • 定義了一個 token_prefix 常量,表示 token 的前綴。通常在 HTTP 請求中,token 會與前綴(如 "Bearer ")一起發送,以標明它是一個授權令牌。
  • 例如,使用 token 時會變成 Bearer <token_value>

5. export function getToken() { return Cookies.get(TokenKey); }

  • 定義了一個 getToken 函數,用來獲取存儲在 cookies 中的 token。它通過 Cookies.get() 方法使用 TokenKey 獲取相應的 token 值。

6. export function setToken(token: string) { return Cookies.set(TokenKey, token); }

  • 定義了一個 setToken 函數,用來將 token 存儲到 cookies 中。它使用 Cookies.set() 方法,將傳入的 token 存儲到 cookies 中,鍵名是 TokenKey
  • 如果是線上環境,可以啟用注釋中的 domain 設置,將 cookie 限定在特定域名下。

7. export function removeToken() { return Cookies.remove(TokenKey); }

  • 定義了一個 removeToken 函數,用來刪除存儲在 cookies 中的 token。它通過 Cookies.remove() 方法,刪除了鍵名為 TokenKey 的 cookie。

總結:

  • 這段代碼主要用來操作用戶的認證信息(token)。它提供了三個函數:
    • getToken() 用來獲取存儲的 token;
    • setToken(token) 用來將 token 存儲到 cookies 中;
    • removeToken() 用來刪除存儲的 token。
  • 這些操作通常用于前端應用中的登錄認證流程。存儲 token 可以用于后續的 API 請求(例如,通過在請求頭中添加 Authorization: Bearer <token> 來驗證用戶身份)。

4. 在 Service 層進行設置 HTTP 請求工具

import { getServiceBaseURL } from "@/utils/service";
import { getToken, token_prefix } from "@/utils/token";
import { createRequest } from "./request";
const isHttpProxy =import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === "Y";
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);export const request = createRequest<App.Service.Response>({baseURL,},{async onRequest(config) {// 請求帶tokenif (getToken()) {// Authorization -> satokenconfig.headers["Authorization"] = token_prefix + getToken();}return config;},isBackendSuccess(response) {return response.data.code === 200;},async onBackendFail(_response) {},transformBackendResponse(response) {return response.data.data;},onError(error) {let message = error.message;if (error.code === "BACKEND_ERROR_CODE") {message = error.response?.data?.msg || message;}window.$message?.error(message);},}
);

之后在發請求的時候 前端會把這個 Token 放到 Header 里面

帶給后端

這段代碼主要用于創建一個 HTTP 請求工具,通常用于前端應用中處理與后端的通信。它使用了封裝的 createRequest 函數來生成請求實例,并配置了多個鉤子函數來處理請求、響應和錯誤等。下面是逐行解釋:

1. import { getServiceBaseURL } from "@/utils/service";

  • @/utils/service 模塊導入 getServiceBaseURL 函數。這個函數通常用于根據環境配置(如開發、生產)來獲取服務的基本 URL。

2. import { getToken, token_prefix } from "@/utils/token";

  • @/utils/token 模塊導入 getTokentoken_prefixgetToken 用來獲取存儲在 cookies 中的用戶 token,token_prefix 是 token 的前綴(通常為 "Bearer ")。

3. import { createRequest } from "./request";

  • 從本地的 request 模塊導入 createRequest 函數。createRequest 用于創建一個 HTTP 請求實例,并可以配置請求的一些默認行為。

4. const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === "Y";

  • 定義了一個 isHttpProxy 變量,判斷當前是否在開發環境(import.meta.env.DEV)以及是否啟用了 HTTP 代理(import.meta.env.VITE_HTTP_PROXY)。這通常用于調試或跨域請求代理。

5. const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);

  • 調用 getServiceBaseURL 函數,傳遞環境配置(import.meta.env)和 isHttpProxy 參數,獲取服務的基礎 URL。baseURL 將作為請求的基礎地址。

6. export const request = createRequest<App.Service.Response>( { baseURL }, { ... });

  • 使用 createRequest 函數創建一個請求實例,傳入配置項。其中 baseURL 是請求的基礎 URL,后面的對象是配置該請求的具體行為。
  • App.Service.Response 表示請求響應的類型,確保請求和響應數據的類型安全。

7. async onRequest(config) { ... }

  • onRequest 是請求鉤子函數,在每個請求發送之前執行。它可以用來修改請求的配置。
  • 這里檢查 getToken() 是否存在,如果存在則在請求頭中添加 Authorization 字段,值為 Bearer <token>,用于身份驗證。

8. isBackendSuccess(response) { return response.data.code === 200; }

  • isBackendSuccess 是用來判斷后端響應是否表示請求成功。根據響應中的 data.code 是否等于 200 來判斷。

9. async onBackendFail(_response) { ... }

  • onBackendFail 是當后端返回失敗時觸發的回調函數。在這個示例中,沒有任何具體的邏輯實現,可能是保留的空函數,或者在后端失敗時要進行的其他處理。

10. transformBackendResponse(response) { return response.data.data; }

  • transformBackendResponse 用于處理從后端響應的數據。默認從響應中提取 data.data 部分,作為最終返回的數據。這樣可以統一處理不同后端返回的數據格式。

11. onError(error) { ... }

  • onError 是請求發生錯誤時的回調函數。在這里,錯誤消息會根據 error.code 來定制,如果錯誤類型是 BACKEND_ERROR_CODE,則從響應中提取錯誤信息。最后,使用 window.$message?.error(message) 顯示錯誤信息。

總結:

  • 這段代碼定義了一個 request 實例,用于執行 API 請求。它封裝了請求配置、響應處理、錯誤處理等多個方面的邏輯。
  • onRequest 鉤子在請求發送前自動添加 token,用于授權。
  • isBackendSuccess 函數用來判斷后端是否成功處理了請求。
  • transformBackendResponse 用于提取后端響應數據的有效部分。
  • onError 函數負責處理錯誤,并向用戶顯示相關的錯誤消息。

通過依賴 和 配置 生效

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

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

相關文章

dtdug匯編指令練習

r 通用寄存器 m 代表內存 imm 代表立即數 r8 代表8位通用寄存器 m8 代表8位內存 imm8 代表8位立即數 mov指令練習 MOV 的語法: mov 目標操作數&#xff0c;源操作數 作用:拷貝源操作數到目標操作數 1、源操作數可以是立即數、通用寄存器、段寄存器、或者內存單元. 2、目標操作數…

vue3模板引用ref

1.訪問模板引用 要在組合式 API 中獲取引用&#xff0c;我們可以使用輔助函數 useTemplateRef() 只可以在組件掛載后才能訪問模板引用 <script setup> import { useTemplateRef, onMounted } from vue// 第一個參數必須與模板中的 ref 值匹配 const input useTempla…

如何用 SSH 訪問 QNX 虛擬機

QNX 虛擬機默認是開啟 SSH 服務的&#xff0c;如果要用 SSH 訪問 QNX 虛擬機&#xff0c;就需要知道虛擬機的 IP 地址&#xff0c;用戶和密碼。本文我們來看看如何獲取這些參數。 1. 啟動虛擬機 啟動過程很慢&#xff0c;請耐心等待。 2. 查看 IP 地址 等待 IDE 連接到虛擬機。…

【Java基礎】Java異常捕捉,throws/throw、finally、try、catch關鍵字的含義與運用

1. Java 異常處理&#xff1a; 異常是程序中的一些錯誤&#xff0c;但并不是所有的錯誤都是異常&#xff0c;并且錯誤有時候是可以避免的。 比如說&#xff0c;你的代碼少了一個分號&#xff0c;那么運行出來結果是提示是錯 java.lang.Error&#xff1b;如果你用System.out.p…

js 中堆、棧、隊列+宏任務+微任務+web workers

文章目錄 js 中堆、棧、隊列介紹js中 堆、棧、隊列的區別與應用拓展&#xff08;宏任務與微任務&#xff09;Web Workers js 中堆、棧、隊列介紹 棧&#xff08;Stack&#xff09; 概念&#xff1a; 棧是一種遵循后進先出&#xff08;LIFO - Last In First Out&#xff09;原則…

java面向對象編程特性概述

目錄 1. 類和對象 2. 封裝&#xff08;Encapsulation&#xff09; 3. 繼承&#xff08;Inheritance&#xff09; 4. 多態&#xff08;Polymorphism&#xff09; 5. 抽象&#xff08;Abstraction&#xff09; (1). 抽象類&#xff08;Abstract Class&#xff09; (2).接口…

React(二)——Admin主頁/Orders頁面/Category頁面

文章目錄 項目地址一、側邊欄1.1 具體實現 二、Header2.1 實現 三、Orders頁面3.1 分頁和搜索3.2 點擊箭頭顯示商家所有訂單3.3 頁碼按鈕以及分頁 四、Category頁面4.1 左側商品添加欄目4.2 右側商品上傳欄 五、Sellers頁面六、Payment Request 頁面&#xff08;百萬數據加載&a…

maven 下載依賴 jhash:2.1.2 和對應 jar 包

原文地址 前言 25年新的一年&#xff0c;那就先更新一篇技術文章吧&#xff0c;這個是這幾天剛遇到的一個有意思的bug&#xff0c;記錄分享一下 原因分析 在使用maven加載一個項目的時&#xff0c;發現maven的依賴一直無法解析&#xff0c;更換阿里云鏡像和中央倉庫都沒辦法…

谷歌開放語音命令數據集,助力初學者踏入音頻識別領域

在人工智能的浪潮中&#xff0c;語音識別技術正逐漸成為我們日常生活的一部分。從智能助手到語音控制設備&#xff0c;語音識別的應用場景越來越廣泛。然而&#xff0c;對于初學者來說&#xff0c;進入這一領域往往面臨諸多挑戰&#xff0c;尤其是缺乏合適的開源數據集和簡單的…

nums[:]數組切片

問題&#xff1a;給定一個整數數組 nums&#xff0c;將數組中的元素向右輪轉 k 個位置&#xff0c;其中 k 是非負數。 使用代碼如下沒有辦法通過測試示例&#xff0c;必須將最后一行代碼改成 nums[:]nums[-k:]nums[:-k]切片形式&#xff1a; 原因&#xff1a;列表的切片操作 …

python-leetcode-三數之和

15. 三數之和 - 力扣&#xff08;LeetCode&#xff09; class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:nums.sort() # 排序n len(nums)res []for i in range(n):# 剪枝&#xff1a;如果當前數 > 0&#xff0c;三數之和不可能為 0if nums[i]…

字節小米等后端崗位C++面試題

C 基礎 引用和指針之間的區別&#xff1f;堆棧和堆中的內存分配有何區別&#xff1f;存在哪些類型的智能指針&#xff1f;unique_ptr 是如何實現的&#xff1f;我們如何強制在 unique_ptr 中僅存在一個對象所有者&#xff1f;shared_ptr 如何工作&#xff1f;對象之間如何同步…

極狐GitLab 正式發布安全版本17.7.1、17.6.3、17.5.5

本分分享極狐GitLab 補丁版本 17.7.1, 17.6.3, 17.5.5 的詳細內容。這幾個版本包含重要的缺陷和安全修復代碼&#xff0c;我們強烈建議所有私有化部署用戶應該立即升級到上述的某一個版本。對于極狐GitLab SaaS&#xff0c;技術團隊已經進行了升級&#xff0c;無需用戶采取任何…

探索綠色能源系統的固態繼電器:2025年展望

隨著全球向綠色能源轉型的加速&#xff0c;對高效、可靠和環保元件的需求從未如此強烈。在這種背景下&#xff0c;國產固態繼電器(SSR)在實現太陽能逆變器、風力渦輪機和儲能系統等關鍵技術方面發揮著關鍵作用。本文探討了綠色能源系統背景下中國固態繼電器行業的前景&#xff…

Rust語言使用iced實現簡單GUI頁面

使用cargo新建一個rust項目 cargo new gui_demo cd gui_demo 編輯Cargo.toml文件 ,添加iced依賴 [package] name "gui_demo" version "0.1.0" edition "2021"[dependencies] iced "0.4.2" 編輯src/main.rs文件&#xff1a; u…

Github提交Pull Request教程 Git基礎掃盲(零基礎易懂)

1 PR是什么&#xff1f; PR&#xff0c;全稱Pull Request&#xff08;拉取請求&#xff09;&#xff0c;是一種非常重要的協作機制&#xff0c;它是 Git 和 GitHub 等代碼托管平臺中常見的功能&#xff0c;被廣泛用于參與社區貢獻&#xff0c;從而促進項目的發展。 PR的整個過…

MySQL 中刪除重復數據 SQL 寫法

要在 MySQL 中刪除重復的數據并只保留一條&#xff0c;可以使用下面的方法&#xff08;要用的時候直接復制小改下條件和表名稱即即可&#xff09; 方法一&#xff1a;使用 left join 子查詢刪除重復數據(推薦) 溫馨提示&#xff1a;本人在 500w 數據下執行此 SQL 耗費 15s-30s…

RabbitMQ 可觀測性最佳實踐

RabbitMQ 簡介 RabbitMQ 是一個開源的消息代理和隊列服務器&#xff0c;用 Erlang 語言編寫&#xff0c;支持多種客戶端。它通過使用交換機&#xff08;Exchanges&#xff09;、隊列&#xff08;Queues&#xff09;和綁定&#xff08;Bindings&#xff09;來路由消息&#xff…

美攝科技PC端視頻編輯解決方案,為企業打造專屬的高效創作平臺

在當今這個信息爆炸的時代&#xff0c;視頻已成為不可或缺的重要內容形式&#xff0c;美攝科技推出了PC端視頻編輯解決方案的私有化部署服務&#xff0c;旨在為企業提供一款量身定制的高效創作平臺。 一、全面功能&#xff0c;滿足企業多樣化需求 美攝科技的PC端視頻編輯解決…

【Oracle篇】深入了解執行計劃中的訪問路徑(含表級別、B樹索引、位圖索引、簇表四大類訪問路徑)

&#x1f4ab;《博主介紹》&#xff1a;?又是一天沒白過&#xff0c;我是奈斯&#xff0c;從事IT領域? &#x1f4ab;《擅長領域》&#xff1a;??擅長阿里云AnalyticDB for MySQL(分布式數據倉庫)、Oracle、MySQL、Linux、prometheus監控&#xff1b;并對SQLserver、NoSQL(…