后端技术选型 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.mzph.cn/web/65766.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用 SSH 访问 QNX 虚拟机

QNX 虚拟机默认是开启 SSH 服务的&#xff0c;如果要用 SSH 访问 QNX 虚拟机&#xff0c;就需要知道虚拟机的 IP 地址&#xff0c;用户和密码。本文我们来看看如何获取这些参数。 1. 启动虚拟机 启动过程很慢&#xff0c;请耐心等待。 2. 查看 IP 地址 等待 IDE 连接到虚拟机。…

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;更换阿里云镜像和中央仓库都没办法…

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]…

极狐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的整个过…

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(…

腾讯云AI代码助手编程挑战赛-厨房助手之AI大厨

腾讯云AI代码助手编程挑战赛-厨房助手之AI大厨 作品简介 身处当今如火箭般迅猛发展的互联网时代&#xff0c;智能聊天助手已然化身成为提升用户体验的关键利器&#xff0c;全方位渗透至人们的数字生活。 紧紧跟随着这股汹涌澎湃的时代浪潮&#xff0c;我毅然投身于极具挑战性…

vscode 无法使用npm, cmd命令行窗口可以正常执行

解决方法&#xff1a; 执行命令获得命令的位置 get-command npm 得到如下 然后删除或者修改 npm.ps1文件 让其不能使用就行。然后重启vscode即可。 pnpm 同理即可 另外加速源 国内镜像源&#xff08;淘宝&#xff09;&#xff1a; npm config set registry https://regist…

简易CPU设计入门:算术逻辑单元(四)

项目代码下载 请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 CSDN文章&#xff1a;下载本项目代码 上述链接为本项目…

Spring Boot 和微服务:快速入门指南

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

VSCode 使用鼠标滚轮控制字体

一、 文件 | 首选项 | 设置 二、单击在 settings.json中编辑 "editor.mouseWheelZoom": true 注注注意&#xff1a;保存哦&#xff01;ctrlS 三、测试 按住ctrl鼠标滚轮&#xff0c;控制字体大小

rabbitmq的三个交换机及简单使用

提前说一下&#xff0c;创建队列&#xff0c;交换机&#xff0c;绑定交换机和队列都是在生产者。消费者只负责监听就行了&#xff0c;不用配其他的。 完成这个场景需要两个服务哦。 1直连交换机-生产者的代码。 在配置类中创建队列&#xff0c;交换机&#xff0c;绑定交换机…

代码随想录算法训练营第3天(链表1)| 203.移除链表元素 707.设计链表 206.反转链表

一、203.移除链表元素 题目&#xff1a;203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 视频&#xff1a;手把手带你学会操作链表 | LeetCode&#xff1a;203.移除链表元素_哔哩哔哩_bilibili 讲解&#xff1a;代码随想录 注意&#xff1a; 针对头结点和非头结点的…