当前位置: 首页 > news >正文

token登录的实现

token登录的实现

我这种token只是简单的实现token,就是后端利用UUID 生成简单随机码,利用随机码作为在Redis中的键,然后存储的用户信息作为值,在每次合理请求的时候对token的有效时间进行刷新(利用拦截器),以确保用户信息的有效性。

为什么要用token

使用令牌(Token)进行身份验证和授权是一种常见的方式,特别适用于分布式和跨域请求的应用程序。

1. 为什么要使用 Token:

  • 无状态性:Token 身份验证是无状态的,不需要在服务器端存储会话信息。每个请求都包含了身份信息,因此服务器不需要维护状态。
  • 跨域支持:Token 可以轻松处理跨域请求,因为令牌可以在 HTTP 请求的头部(通常是 Authorization 头部)中传递,而不受同源策略的限制。
  • 扩展性:Token 可以包含任意信息,因此可以用于传递用户权限、角色、过期时间等信息。

2. Token 使用逻辑:

  • 用户登录成功后,生成一个 Token 并将用户信息存储在服务器端(如 Redis)以便快速验证和获取用户信息。
  • 向前端返回 Token。
  • 前端将 Token 存储在本地(通常是 sessionStorage 或 localStorage)。
  • 在每个后续的请求中,前端将 Token 通过请求头(通常是 Authorization 头)发送给后端。
  • 后端从请求头中获取 Token,验证其合法性,并使用 Token 获取用户信息。

后端(Spring Boot)示例:

定义login接口

@GetMapping("/login")public BaseResponse<String> login(String username,String password){LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.eq(User::getUsername,username);User one = userService.getOne(lambdaQueryWrapper);if(one == null){throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);}String token = UUID.randomUUID().toString();redisTemplate.opsForHash().putAll("test:user:"+token, BeanUtil.beanToMap(one));redisTemplate.expire("test:user:" + token,2, TimeUnit.MINUTES);return ResultUtils.success(token);}

定义一个获取用户信息的其他接口

@GetMapping("/get")public BaseResponse<User> get(){return ResultUtils.success(UserHolder.getValue());}

创建拦截器:

public class LoginInterceptor implements HandlerInterceptor {private RedisTemplate<String,Object> redisTemplate;public LoginInterceptor(RedisTemplate<String,Object> template){this.redisTemplate = template;}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {// 获取 sessionString token = request.getHeader("Authorization");// 检查用户是否已登录User user = new User();BeanUtil.fillBeanWithMap(redisTemplate.opsForHash().entries("test:user:"+token),user,false);if(user == null|| BeanUtil.isEmpty(user)){throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);}redisTemplate.expire("test:user:"+token,2, TimeUnit.MINUTES);// 将用户数据存储到 ThreadLocal 中,以便在整个请求周期内访问UserHolder.setValue(user);// 进行其他逻辑验证,根据需求自行添加return true; // 允许请求继续执行}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// 在请求处理之后执行,可以对 ModelAndView 进行修改}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {// 在请求完成之后执行,用于资源清理等操作// 清理 ThreadLocal 中的用户数据,防止内存泄漏UserHolder.clear();}

注册拦截器:

@Configuration
public class MvcConfig implements WebMvcConfigurer {@Resourceprivate RedisTemplate<String,Object> redisTemplate;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登录拦截器registry.addInterceptor(new LoginInterceptor(redisTemplate)).addPathPatterns("/**").excludePathPatterns("/user/login");}
}

使用结果截图

结果返回了一个token,这个token前端拿到以后要保存到sessionStorage或者LocalStorage里面,再把这个token送到请求头中,就可以啦

在这里插入图片描述

另一个请求:

设置请求头

设置Authorization
在这里插入图片描述
然后发起就可以得到啦
在这里插入图片描述

如果没有authorization就是得到未登录结果

在这里插入图片描述

前端(Vue.js)示例:

<!-- Login.vue -->
<template><div><input v-model="username" placeholder="Username" /><input type="password" v-model="password" placeholder="Password" /><button @click="login">Login</button></div>
</template><script>
export default {data() {return {username: '',password: ''};},methods: {login() {// 发送登录请求,获取 Tokenaxios.post('/api/user/login', { username: this.username, password: this.password }).then(response => {const token = response.data.token;// 存储 Token 到 sessionStoragesessionStorage.setItem('token', token);// 跳转到其他页面或进行其他操作}).catch(error => {console.error('Login failed:', error);});}}
};
</script>

相关文章:

token登录的实现

token登录的实现 我这种token只是简单的实现token&#xff0c;就是后端利用UUID 生成简单随机码&#xff0c;利用随机码作为在Redis中的键&#xff0c;然后存储的用户信息作为值&#xff0c;在每次合理请求的时候对token的有效时间进行刷新&#xff08;利用拦截器&#xff09;&…...

GO语言从入门到实战-Go语言课程介绍

为什么选择 Go 语言来完成这么大一个项目呢&#xff1f;我们不妨回到 Go 语言的源头看一看。 Go 语言的初步设想始于 2007 年&#xff0c;当时 Go 语言的三位创始人是想通过开发一种新型的语言来解决 Google 在软件开发中面临的问题&#xff1a; 多核硬件架构&#xff1b;超大…...

七天学会C语言-第六天(指针)

1.指针变量与普通变量 指针变量与普通变量是C语言中的两种不同类型的变量&#xff0c;它们有一些重要的区别和联系。 普通变量是一种存储数据的容器&#xff0c;可以直接存储和访问数据的值。&#xff1a; int num 10; // 定义一个整数型普通变量num&#xff0c;赋值为10在例…...

2023年腾讯云轻量服务器测评:16核 32G 28M 配置CPU测试

腾讯云轻量应用服务器16核32G28M配置优惠价3468元15个月&#xff08;支持免费续3个月/送同配置3个月&#xff09;&#xff0c;轻量应用服务器具有100%CPU性能&#xff0c;系统盘为380GB SSD盘&#xff0c;28M带宽下载速度3584KB/秒&#xff0c;月流量6000GB&#xff0c;折合每天…...

macos (M2芯片)搭建flutter环境

安装的版本3.13.4、电脑上没有安装过android studio、安装过brew 1.在终端运行sudo softwareupdate --install-rosetta --agree-to-license&#xff0c;下图展示安装成功的效果 2.下载以下安装包来获取最新的 stable Flutter SDK 3.解压&#xff0c;⚠️注意下载安装sdk的包名…...

Xilinx FPGA未使用管脚上下拉状态配置(ISE和Vivado环境)

文章目录 ISE开发环境Vivado开发环境方式1&#xff1a;XDC文件约束方式2&#xff1a;生成选项配置 ISE开发环境 ISE开发环境&#xff0c;可在如下Bit流文件生成选项中配置。 右键点击Generate Programming File&#xff0c;选择Process Properties&#xff0c; 在弹出的窗口选…...

数据结构---链表(java)

目录 1. 链表 2. 创建Node 3. 增加 4. 获取元素 5. 删除 6. 遍历链表 7. 查找元素是否存在 8. 链栈的实现 9. 链队的实现 1. 链表 数据存放在"Node"结点中 优点&#xff1a;不用考虑扩容和缩容的问题&#xff0c;实现了动态存储数据 缺点&#xff1a;没有…...

Qt --- Day02

实现效果&#xff1a; 点击登录&#xff0c;检验用户密码是否正确&#xff0c;正确则弹出消息框&#xff0c;点击ok转到另一个页面 不正确跳出错误消息框&#xff0c;默认选线为Cancel&#xff0c;点击Yes继续登录 点击Cancel跳出问题消息框&#xff0c;默认选项No&#xff0c…...

Redis 集合(Set)快速指南 | Navicat

Redis 支持通过多种数据类型来存储项目集合。其中&#xff0c;包括列表、集合和哈希。上周的博文介绍了列表&#xff08;List&#xff09;数据类型并重点介绍了一些用于管理列表&#xff08;List&#xff09;的主要命令。在今天的文章中&#xff0c;我们将转向关注集合&#xf…...

【华为云云耀云服务器L实例评测】- 云原生实践,快捷部署人才招聘平台容器化技术方案!

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…...

【Java】泛型 之 什么是泛型

什么是泛型 泛型是一种“代码模板”&#xff0c;可以用一套代码套用各种类型。 在讲解什么是泛型之前&#xff0c;我们先观察Java标准库提供的ArrayList&#xff0c;它可以看作“可变长度”的数组&#xff0c;因为用起来比数组更方便。 实际上ArrayList内部就是一个Object[]…...

Python yaml 详解

文章目录 1 概述1.1 特点1.2 导入 2 对象2.1 字典2.2 数组2.3 复合结构 3 操作3.1 读取3.2 写入 1 概述 1.1 特点 yaml 文件是一种数据序列化语言&#xff0c;广泛用于配置文件、日志文件等特点&#xff1a; ① 大小写敏感。② 使用缩进表示层级关系。缩进时不允许使用 Tab 键…...

RabbitMQ消息可靠性(二)-- 消费者消息确认

一、消费者消息确认是什么&#xff1f; 在这种机制下&#xff0c;消费者在接收到消息后&#xff0c;需要向 RabbitMQ 发送确认信息&#xff0c;告知 RabbitMQ 已经接收到该消息&#xff0c;并已经处理完毕。如果 RabbitMQ 没有接收到确认信息&#xff0c;则会将该消息重新加入…...

【python第7课 实例,类】

文章目录 一、实例1.1实例的变量1.2实例方法1.3 构造方法1.4析构函数1.4预置实例属性&#xff1a; 二&#xff0c;类1.1类变量1.2类方法1.3静态方法1.4类属性的增删改查 一、实例 1.1实例的变量 使用示例 class dog:def __init__(self,k,c,a):self.kinds kself.color csel…...

RocketMQ源码解析(上)

一、ACL权限控制 应用场景&#xff1a; ​RocketMQ提供了针对队列、用户等不同维度的非常全面的权限管理机制。通常来说&#xff0c;RocketMQ作为一个内部服务&#xff0c;是不需要进行权限控制的&#xff0c;但是&#xff0c;如果要通过RocketMQ进行跨部门甚至跨公司的合作&…...

Webpack打包CSS文件,解决You may need an appropriate loader to handle this file type报错

在项目文件夹下创建webpack.config.js文件&#xff0c;该文件就是Webpack的配置文件 注意&#xff1a;该文件中遵循Node.js的代码格式规范 &#xff0c;需要对导出配置文件中的内容 Webpack在默认情况下只能打包js文件&#xff0c;如果我们希望他能够打包其他类型的文件&#…...

轮换对称性

二重积分 普通对称性–D关于 y x yx yx对称&#xff1a; ∬ D f ( x , y ) d σ { 2 ∬ D 1 f ( x , y ) d σ f ( x , y ) f ( y , x ) 0 f ( x , y ) − f ( y , x ) \iint_{D}f(x,y)d\sigma\begin{cases} 2\iint_{D_1}f(x,y)d\sigma\ \ \ \ \ \ f(x,y)f(y,x) \\ 0 \ \…...

【MySQL基础】--- 约束

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、什么…...

ROS2 的行为树 — 第 1 部分:解锁高级机器人决策和控制

一、说明 在复杂而迷人的机器人世界中&#xff0c;行为树&#xff08;BT&#xff09;已成为决策过程中不可或缺的一部分。它们提供了一种结构化、模块化和高效的方法来对机器人的行为进行编程。BT起源于视频游戏行业&#xff0c;用于控制非玩家角色&#xff0c;他们在机器人领域…...

kafka事务的详解

一 kafka事务的机制 1.1 kafka的事务机制 通过事务机制&#xff0c;KAFKA 可以实现对多个 topic 的多个 partition 的原子性的写入&#xff0c;即处于同一个事务内的所有消息&#xff0c;不管最终需要落地到哪个 topic 的哪个 partition, 最终结果都是要么全部写成功&#xf…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...

13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析

LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...