Spring Boot 笔记 007 创建接口_登录
1.1 登录接口需求


1.2 JWT令牌
1.2.1 JWT原理

1.2.2 引入JWT坐标

1.2.3 单元测试
1.2.3.1 引入springboot单元测试坐标

1.2.3.2 在单元测试文件夹中创建测试类

1.2.3.3 运行测试类中的生成和解析方法
package com.geji;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;import java.util.Date;
import java.util.HashMap;
import java.util.Map;public class JwtTest {@Testpublic void testGen() {Map<String, Object> claims = new HashMap<>();claims.put("id", 1);claims.put("username", "张三");//生成jwt的代码String token = JWT.create().withClaim("user", claims)//添加载荷.withExpiresAt(new Date(System.currentTimeMillis() + 1000*60))//添加过期时间.sign(Algorithm.HMAC256("geji"));//指定算法,配置秘钥System.out.println(token);}@Testpublic void testParse() {//定义字符串,模拟用户传递过来的tokenString token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3MDc4MTA0NTh9.Ir8IDQ673BoD86ubm8nMo_F91P-ytCd2_MaDzi5mONo";JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("geji")).build();DecodedJWT decodedJWT = jwtVerifier.verify(token);//验证token,生成一个解析后的JWT对象Map<String, Claim> claims = decodedJWT.getClaims();System.out.println(claims.get("user"));//如果篡改了头部和载荷部分的数据,那么验证失败//如果秘钥改了,验证失败//token过期}
}
1.2.4 在utils包中添加jwt工具类

package com.geji.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static final String KEY = "geji";//接收业务数据,生成token并返回public static String genToken(Map<String, Object> claims) {return JWT.create().withClaim("claims", claims).withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 )).sign(Algorithm.HMAC256(KEY));}//接收token,验证token,并返回业务数据public static Map<String, Object> parseToken(String token) {return JWT.require(Algorithm.HMAC256(KEY)).build().verify(token).getClaim("claims").asMap();}}
1.3 拦截器
1.3.1 编写拦截器

package com.geji.interceptors;import com.geji.pojo.Result;
import com.geji.utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import java.util.Map;@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//令牌验证String token = request.getHeader("Authorization");//验证tokentry{Map<String,Object> claims= JwtUtil.parseToken(token);return true;}catch (Exception e){response.setStatus(401);return false;}}}
1.3.2 注册拦截器,登录和注册接口需要放行

package com.geji.config;import com.geji.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//登录接口和注册接口不拦截registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login","/user/register");}
}
1.4 编写controller
1.4.1 编写login controller

package com.geji.controller;import com.geji.pojo.Result;
import com.geji.pojo.User;
import com.geji.service.UserService;
import com.geji.utils.JwtUtil;
import com.geji.utils.Md5Util;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("/user")
@Validated
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/register")public Result register(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {//查询用户User u = userService.findByUserName(username);if (u == null) {//没有占用//注册userService.register(username, password);return Result.success();} else {//占用return Result.error("用户名已被占用");}}@PostMapping("/login")public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {//根据用户名查询用户User loginUser = userService.findByUserName(username);//判断该用户是否存在if (loginUser == null) {return Result.error("用户名错误");}//判断密码是否正确 loginUser对象中的password是密文if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {//登录成功Map<String, Object> claims = new HashMap<>();claims.put("id", loginUser.getId());claims.put("username", loginUser.getUsername());String token = JwtUtil.genToken(claims);//把token存储到redis中
// ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
// operations.set(token,token,1, TimeUnit.HOURS);return Result.success(token);}return Result.error("密码错误");}
}
1.4.2 编写article list controller

package com.geji.controller;import com.geji.pojo.Result;
import com.geji.utils.JwtUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
@RequestMapping("/article")
public class ArticleController {@GetMapping("/list")public Result<String> list(){return Result.success("所有文章数据...");}
}
1.5 测试
1.5.1 获取令牌

1.5.2 带请求头

1.4.3 不带请求头

相关文章:
Spring Boot 笔记 007 创建接口_登录
1.1 登录接口需求 1.2 JWT令牌 1.2.1 JWT原理 1.2.2 引入JWT坐标 1.2.3 单元测试 1.2.3.1 引入springboot单元测试坐标 1.2.3.2 在单元测试文件夹中创建测试类 1.2.3.3 运行测试类中的生成和解析方法 package com.geji;import com.auth0.jwt.JWT; import com.auth0.jwt.JWTV…...
java数据结构与算法刷题-----LeetCode594. 最长和谐子序列
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 解题思路 子序列要尽可能长,并且最大值和最小值之间的差&#…...
数据分析基础之《pandas(6)—高级处理》
一、缺失值处理 1、如何处理nan 两种思路: (1)如果样本量很大,可以删除含有缺失值的样本 (2)如果要珍惜每一个样本,可以替换/插补(计算平均值或中位数) 2、判断数据是否…...
IOS破解软件安装教程
对于很多iOS用户而言,获取软件的途径显得较为单一,必须通过App Store进行下载安装。 这样的限制,时常让人羡慕安卓系统那些自由下载各类版本软件的便捷。 心中不禁生出疑问:难道iOS世界里,就不存在所谓的“破解版”软件…...
[缓存] - 1.缓存共性问题
1. 缓存的作用 为什么需要缓存呢?缓存主要解决两个问题,一个是提高应用程序的性能,降低请求响应的延时;一个是提高应用程序的并发性。 1.1 高并发 一般来说, 如果 10Wqps,或者20Wqps ,可使用分布…...
Python爬虫——解析库安装(1)
目录 1.lxml安装2.Beautiful Soup安装3.pyquery 的安装 我创建了一个社区,欢迎大家一起学习交流。社区名称:Spider学习交流 注:该系列教程已经默认用户安装了Pycharm和Anaconda,未安装的可以参考我之前的博客有将如何安装。同时默…...
中科大计网学习记录笔记(十一):CDN
前言: 学习视频:中科大郑烇、杨坚全套《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》课程 该视频是B站非常著名的计网学习视频,但相信很多朋友和我一样在听完前面的部分发现信…...
[缓存] - 2.分布式缓存重磅中间件 Redis
1. 高性能 尽量使用短key 不要存过大的数据 避免使用keys *:使用SCAN,来代替 在存到Redis之前压缩数据 设置 key 有效期 选择回收策略(maxmemory-policy) 减少不必要的连接 限制redis的内存大小(防止swap,OOM) slowLog …...
1191. 家谱树(拓扑排序,模板题)
活动 - AcWing 有个人的家族很大,辈分关系很混乱,请你帮整理一下这种关系。 给出每个人的孩子的信息。 输出一个序列,使得每个人的孩子都比那个人后列出。 输入格式 第 11 行一个整数 n,表示家族的人数; 接下来 …...
CSS之BFC
BFC概念 BFC(Block Formatting Context)即块级格式化上下文,是Web页面的可视CSS渲染的一部分。它是一个独立的渲染区域,让其中的元素在布局上与外部的元素互不影响。简单来说,BFC提供了一个环境,允许内部的…...
2024 年合并 PDF 文件的免费 PDF 合并软件榜单
合并 PDF 是当今人们寻找的最重要的功能之一。在本文中,您将了解前五名的 PDF 合并软件以及详细的介绍,以便您选择最佳的。如果您想将所有重要信息都放在一个文件中,而不是在不同的文件中查找,那么合并 PDF 文件是必要的。通过这种…...
Python教程56:海龟画图turtle画kitty猫
---------------turtle源码集合--------------- Python教程91:关于海龟画图,Turtle模块需要学习的知识点 Python教程51:海龟画图turtle画(三角形、正方形、五边形、六边形、圆、同心圆、边切圆,五角星,椭…...
c入门第十篇——指针入门
一句话来说: 指针就是存储了内存地址值的变量。 在前面讨论传值和传址的时候,我们就已经开始使用了指针来传递地址。 在正式介绍指针之前,我们先来简单了解一下内存。内存可以简单的理解为一排连续的房子的街道,每个房子都有自己的地址&#…...
pwn学习笔记(3)ret2syscall
pwn学习笔记(3) ROP原理: ROP(Return Oriented Programming)返回导向编程,主要思想是通过在程序中已有的小片段(gadgets)来改变某些寄存器或者变量的值,从而控制程序的执行流程。 栈溢出–…...
React18原理: 生命周期中特别注意事项
概述 生命周期就是一个组件从诞生到销毁的全过程(包含错误捕获,这里暂且不聊这个)react 在组件的生命周期中注册了一系列的钩子函数支持开发者在其中嵌入代码,并在适当的时机运行生命周期本质上就是组件中的钩子函数,主要有三个主要的钩子 挂…...
【C语言】Linux内核bind系统调用代码
一、Linux 4.9内核bind系统调用代码注释 int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) {struct socket *sock; // 定义socket对象的指针struct sockaddr_storage address; // 用于存储从用户空间复制过来的地址int err…...
Ubuntu下Anaconda+PyCharm搭建PyTorch环境
这里主要介绍在condapytorch都正确安装的前提下,如何通过pycharm建立开发环境; Ubuntu下AnacondaPyCharm搭建PyTorch环境 系统环境:Ubuntu22.04 conda: conda 23.11.0 pycharm:如下 condapytorch的安装教程介绍,请点击这里&…...
酷开科技荣获“消费者服务之星”称号后的未来展望
恭喜酷开科技荣获2023年第四季度黑猫平台“消费者服务之星”称号!这是对酷开科技长期以来坚持用户至上、用心服务的肯定和认可。作为OTT行业的佼佼者,酷开科技一直秉承着“以用户为中心”的服务理念,不断追求卓越品质,为用户提供更…...
UVA1449 Dominating Patterns 题解
UVA1449 Dominating Patterns 题解 板子题诶。 解法 AC 自动机模板题,因为数据范围比较小,所以不加拓扑排序优化建图即可通过本题。这里简单介绍一下拓扑排序优化建图。 在查找时,每次都暴力的条 f a i l fail fail 指针是很消耗时间的&…...
【C语言】数据结构#实现堆
目录 (一)堆 (1)堆区与数据结构的堆 (二)头文件 (三)功能实现 (1)堆的初始化 (2)堆的销毁 (3)插入数据 …...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
