【JWT的使用】
文章目录
- 前言
- 1、用户登录
- 1.1 JWT
- ThreadLocal
- 2.1 代码实现
- 2.1.1 ThreadLocal工具类
- 2.2.2 定义拦截器
- 2.2.3 注册拦截器
前言
1、用户登录
1.1 JWT
JSON Web Token简称JWT,用于对应用程序上用户进行身份验证的标记。使用 JWTS 之后不需要保存用户的 cookie 或其他session数据,同时可保证应用程序的安全。
JWT是经过加密处理与校验处理的字符串,形式为:A.B.C
- –A由JWT头部信息header加密得到
- –B由JWT用到的身份验证信息JSON数据加密得到
- –C由A和B加密得到,是校验部分
- –官方测试网站: https://jwt.io/
@Testpublic void testCreateToken() {//生成token//1、准备数据Map map = new HashMap();map.put("id",1);map.put("mobile","13800138000");//2、使用JWT工具类生成tokenlong now = System.currentTimeMillis();String token = Jwts.builder().signWith(SignatureAlgorithm.HS512, "itcast") //指定加密算法.setClaims(map)//指定写入的数据.setExpiration(new Date(now + 5000)) //设置失效时间.compact();System.out.println(token);}@Testpublic void testParseToken() {String token = "eyJhbGciOiJIUzUxMiJ9.e1yJtb2JpbGUiOiIxMzgwMDEzODAwMCIsImlkIjoxLCJleHAiOjE2MTgzOTA4NzB9.WhZfFSJNEZJGeZAHqMaVIslvzvkFzQ1FCLCULSaR-yZYprbzgmuxNaSr3oW__zRFkBCnNRGllzaKb0ZJujs1GA";//解析tokentry {Claims claims = Jwts.parser().setSigningKey("itcast").parseClaimsJws(token).getBody();Object id = claims.get("id");Object mobile = claims.get("mobile");System.out.println(id + "--" + mobile);}catch (ExpiredJwtException e) {System.out.println("token已过期");}catch (SignatureException e) {System.out.println("token不合法");}}
JWT工具类
public class JwtUtils {// TOKEN的有效期1小时(S)private static final int TOKEN_TIME_OUT = 3_600;// 加密KEYprivate static final String TOKEN_SECRET = "itcast";// 生成Tokenpublic static String getToken(Map params){long currentTime = System.currentTimeMillis();return Jwts.builder().signWith(SignatureAlgorithm.HS512, TOKEN_SECRET) //加密方式.setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000)) //过期时间戳.addClaims(params).compact();}/*** 获取Token中的claims信息*/public static Claims getClaims(String token) {return Jwts.parser().setSigningKey(TOKEN_SECRET).parseClaimsJws(token).getBody();}/*** 是否有效 true-有效,false-失效*/public static boolean verifyToken(String token) {if(StringUtils.isEmpty(token)) {return false;}try {Claims claims = Jwts.parser().setSigningKey("itcast").parseClaimsJws(token).getBody();}catch (Exception e) {return false;}return true;}
}
ThreadLocal
-
线程内部的存储类,赋予了线程存储数据的能力。
-
线程内调用的方法都可以从ThreadLocal中获取同一个对象。
-
多个线程中ThreadLocal数据相互隔离
2.1 代码实现
2.1.1 ThreadLocal工具类
定义ThreadLocal工具类,仅需要调用set方法即可将数据存入ThreadLocal中
package com.tanhua.server.interceptor;import com.tanhua.model.domain.User;/*** @author Administrator*/
public class UserHolder {private static ThreadLocal<User> tl = new ThreadLocal<User>();/*** 保存数据到线程*/public static void set(User user) {tl.set(user);}/*** 获取线程中的用户信息*/public static User get() {return tl.get();}/*** 从当前线程,获取用户对象的id*/public static Long getUserId() {if (tl.get() == null) {return null;}return tl.get().getId();}/*** 从当前线程,获取用户对象的手机号码*/public static String getMobile() {if (tl.get() == null) {return null;}return tl.get().getMobile();}/*** 移除线程中数据*/public static void remove() {tl.remove();}
}
2.2.2 定义拦截器
定义拦截器,在前置拦截方法preHandle中解析token并验证有效性,如果失效返回状态码401。如果有效,解析User对象,存入ThreadLocal中
package com.tanhua.server.interceptor;import com.tanhua.model.domain.User;
import com.tanhua.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** @author Administrator*/
public class TokenInterceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1、获取请求头String token = request.getHeader("Authorization");//2、使用工具类,判断token是否有效boolean verifyToken = JwtUtils.verifyToken(token);//3、如果token失效,返回状态码401,拦截if(!verifyToken) {response.setStatus(401);return false;}//4、如果token正常可用,放行//解析token,获取id和手机号码,Claims claims = JwtUtils.getClaims(token);String mobile = (String) claims.get("mobile");Integer id = (Integer) claims.get("id");//构造User对象,存入ThreadlocalUser user = new User();user.setId(Long.valueOf(id));user.setMobile(mobile);UserHolder.set(user);return true;}//清空@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {UserHolder.remove();}
}
2.2.3 注册拦截器
拦截器需要注册到MVC容器中
/*** @author Administrator*/
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/login", "/user/loginVerification");}
}
package com.tanhua.server.controller;import com.tanhua.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
@RequestMapping("/user")
public class LoginController {@Autowiredprivate UserService userService;/*** 获取登录验证* 请求参数:phone(Map)* 响应:void*ResponseEntity* @return*/@PostMapping("/login")public ResponseEntity login(@RequestBody Map map){String phone = (String) map.get("phone");userService.sendMsg(phone);
// return ResponseEntity.status(500).body("出错了");return ResponseEntity.ok(null);//正常返回状态码200}/***检验登录* /user/loginVerification* phone,verificationCode*/@PostMapping("/loginVerification")public ResponseEntity loginVerification(@RequestBody Map map){//1.调用map集合获取请求参数String phone = (String) map.get("phone");String code = (String) map.get("verificationCode");//2.调用userService完成用户登录Map retMap = userService.loginVerification(phone,code);//3.构造返回return ResponseEntity.ok(retMap);}
}
package com.tanhua.server.service;import com.tanhua.autoconfig.template.SmsTemplate;
import com.tanhua.commons.utils.JwtUtils;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.model.domain.User;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.server.exception.BusinessException;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.time.Duration;
import java.util.HashMap;
import java.util.Map;@Service
public class UserService {@Autowiredprivate SmsTemplate smsTemplate;@Autowiredprivate RedisTemplate<String,String> redisTemplate;@DubboReferenceprivate UserApi userApi;/*** 发送短信验证码* @param phone*/public void sendMsg(String phone) {//1.随机生成6位数字
// String code = RandomStringUtils.randomNumeric(6);String code = "123456";//2.调用templat对象,发送手机短信
// smsTemplate.sendSms(phone,code);//3.将验证码存入到redisredisTemplate.opsForValue().set("CHECK_CODE" + phone,code, Duration.ofMinutes(5));}/*** 验证登录* @param phone* @param code* @return*/public Map loginVerification(String phone, String code) {//1.从redis中获取下发的验证码String redisCode = redisTemplate.opsForValue().get("CHECK_CODE" + phone);//2.对验证码进行校验(验证码是否存在,是否和输入的验证码是否一致)if (StringUtils.isEmpty(redisCode) || !redisCode.equals(code)){//验证码无效throw new BusinessException(ErrorResult.loginError());}//3.删除redis中的验证码redisTemplate.delete("CHECK_CODE"+phone);//4.通过手机号码查询用户User user = userApi.findByMobile(phone);boolean isNew = false;//5.如果用户不存在,创建用户保存到数据库中if (user == null){user = new User();user.setMobile(phone);user.setPassword(DigestUtils.md5Hex("123456"));Long userId = userApi.save(user);user.setId(userId);isNew = true;}//6.通过JWT生成token(存入id和手机号码)Map tokenMap = new HashMap();tokenMap.put("id",user.getId());tokenMap.put("mobile",phone);String token = JwtUtils.getToken(tokenMap);//7.构造返回值Map retMap = new HashMap();retMap.put("token",token);retMap.put("isNew",isNew);return retMap;}
}相关文章:
【JWT的使用】
文章目录 前言1、用户登录1.1 JWTThreadLocal 2.1 代码实现2.1.1 ThreadLocal工具类2.2.2 定义拦截器2.2.3 注册拦截器 前言 1、用户登录 1.1 JWT JSON Web Token简称JWT,用于对应用程序上用户进行身份验证的标记。使用 JWTS 之后不需要保存用户的 cookie 或其他…...
Python获取音视频时长
Python获取音视频时长 Python获取音视频时长1、安装插件2、获取音视频时长.py3、打包exe4、下载地址 Python获取音视频时长 1、安装插件 pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple2、获取音视频时长.py 上代码:获取音视频时长.py # -*-…...
TCP四次握手为什么客户端等待的时间是2MSL
目录 什么是MSL从第三次握手开始分析总结 什么是MSL MSL是Maximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。 从第三次握手开始分析 第三次握手服务端…...
Android Studio 启用设备远程调试配置完整步聚
启用手机设置->开发者选项-无线调试,然后选择允许 已启用后无线调试变成绿色 ,点击无线调试进入详情页面 点击Android Studio的Device Manager 下的WIFI图标 会弹出下图窗口 打开手机的开发者选项中的WIFI调试(无线调试)下的使用二维码配对设备进行扫描. 设备配对成功后手机…...
玩转LaTeX(三)【数学公式(基础)、矩阵、多行公式】
数学公式基础 导言区(引包) \usepackage{amsmath} %带星号的eqution 正文区 \begin{document}%数学公式初步 \section{简介} \LaTeX{}将排版内容分为文本模式和数学模式。文本模式用于普通文本排版,数学模式用于数学公式排版。 …...
jenkins 配置git
在linux 中输入 保证git 安装成功 git --version使用查看git 安装目录(非源码安装直接用yum 安装的) which gitjenkins 中到 系统管理–>全局工具配置–> Git installations 新建一个项目 选择自由风格 源码管理选择 git 如果使用的是码云&a…...
单机部署MinIo并设置开机自启
MinIO 是高性能的对象存储,是为海量数据存储、人工智能、大数据分析而设计的,它完全兼容Amazon S3接口,单个对象最大可达5TB,适合存储海量图片、视频、日志文件、备份数据和容器/虚拟机镜像等。MinIO主要采用Golang语言实现&#…...
Latex | 使用MATLAB生成.eps矢量图并导入Latex中的方法
一、问题描述 用Latex时写paper时,要导入MATLAB生成的图进去 二、解决思路 (1)在MATLAB生成图片的窗口中,导出.eps矢量图 (2)把图上传到overleaf的目录 (3)在文中添加相应代码 三…...
宝塔面板定时任务重启各种服务
一个php项目,laravel框架,使用了nginx php redis mysql 还有进程守护supervisor,用于laravel的异步队列进程queue,当服务器重启后有可能部分服务没有成功启动这个时候可以用定时任务去检查服务状态,然后对不正常的自动…...
Ansible playbook编写
目录 palybooks 组成示例:运行palybook定义,引用变量when 条件判断循环Templates模块tags 模块 palybooks 组成 Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行Variables:变量Temp…...
个人博客系统 -- 登录页面添加图片验证码
目录 1. 功能展示 2. 前段代码 3. 后端代码 1. 功能展示 在登录页面添加验证码登录 1. 检测到没有输入验证码或者输入的验证码错误时,进行弹窗提示.并且刷新当前验证码图片 2. 点击验证码进行刷新 2. 前段代码 1. 添加验证码标签,在密码的下面,在login.html进行修改 主要…...
剑指offer10-I.斐波那契数列
学计算机的对这道题肯定不陌生,我记得是学C语言的时候学递归的时候有这道题,于是我就世界用递归写了如下代码: class Solution {public int fib(int n) {if(n1) return 1;if(n0) return 0;return (fib(n-1) fib(n-2)) % 1000000007;} } 到…...
13年测试经验,性能测试-压力测试指标分析总结,看这篇就够了...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 一般推荐…...
大数据课程D3——hadoop的Source
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Source的AVRO Source; ⚪ 掌握Source的Exec Source; ⚪ 掌握Source的Spooling Directory Source; ⚪ 掌握Source的Netcat Source; ⚪ 掌握Source的Sequence Generator Source;…...
F5 LTM 知识点和实验 4-持久化
第四章:持久化 持久化: 大多数应用都是有状态的,比如,使用一个购物网站,最重要的是用户在放入一个商品之后,刷新网页要能继续看到购物车里的东西,这就需要请求报文发到同一个后端服务器上,持久化就能完成这个功能。 持久化支持一下几种场景: 源地址目标地址SSLSIPH…...
SpringBoot之WebMvcConfigurer详解
目录 一、基本介绍 二、WebMvcConfigurer接口展示 三、常用方法列举 3.1 addInterceptors:添加拦截器 3.2 addResourceHandlers:添加静态资源 3.3 addCorsMappings:添加跨域 编写的初衷是为了自己巩固复习,如果能帮到你将是…...
WPF实战学习笔记22-添加自定义询问窗口
添加自定义询问窗口 详细代码:https://github.com/DongLiqiang/Mytodo/commit/221de6b2344d5c861f1d3b2fbb2480e3e3b35c26 添加自定义询问窗口显示方法 修改文件Mytodo.Extensions.DialogExtension 添加内容,类中添加内容 /// <summary> /// …...
Spring Boot项目的创建
hi 大家好,又见面了,今天继续讲解Spring Boot 文章目录 🐶1.什么是Spring Boot?🐶2.Spring Boot的优势🐶3.Spring Boot项目创建🌼3.1使用ieda创建🥝3.1.1下载插件Spring Boot Helper🥝3.1.2创建项目 &…...
Python加载数据的5种方法
大家好,今天回顾五种引入数据的Python技术,并附有代码实例参考。 我们将使用Numpy、Pandas和Pickle包,所以要导入它们: import numpy as np import pandas as pd import pickle Manual功能 这是最困难的,因为你必须…...
QPoint、QLine、QSize、QRect
QPoint、QLine、QSize、QRect QPointQLineQSizeQRect QPoint // 构造函数 // 构造一个坐标原点, 即(0, 0) QPoint::QPoint(); // 参数为 x轴坐标, y轴坐标 QPoint::QPoint(int xpos, int ypos);// 设置x轴坐标 void QPoint::setX(int x); // 设置y轴坐标 void QPoint::setY(in…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
