【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…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...