SpringBoot通过拦截器和JWT令牌实现登录验证

1. Jwt 工具类

引入依赖

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version>
</dependency>

JwtUtil 类包含了两个静态方法:generateToken() 用于生成 JWT,validateToken() 用于验证 JWT

public class JwtUtil {//密钥private static final String SECRET_KEY = "xxxxxxxxx";// 过期时间60分钟private static final long EXPIRE_TIME = 60 * 60 * 1000;/*** 生成签名** @param claims* @return*/public static String generateToken(Map<String, Object> claims) {var jwtBuilder = JWT.create();// 设置传入的字典中的声明for (Map.Entry<String, Object> entry : claims.entrySet()) {jwtBuilder.withClaim(entry.getKey(), entry.getValue().toString());}//过期时间Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);return jwtBuilder.withExpiresAt(date).sign(algorithm);}/*** 校验token是否正确** @param token* @return*/public static boolean validateToken(String token) {try {if (token.startsWith("Bearer ")) {token = token.replace("Bearer ", "");return false;}Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);DecodedJWT jwt = JWT.require(algorithm).build().verify(token);return true;} catch (Exception exception) {return false;}}/*** 获得token中的用户信息(无需secret解密也能获得)** @param token* @return*/public static String getUsername(String token) {try {if (token.startsWith("Bearer ")) {token = token.replace("Bearer ", "");}DecodedJWT jwt = JWT.decode(token);return jwt.getClaim("userName").asString();} catch (JWTDecodeException e) {return null;}}
}

2. 匿名访问注解

自定义匿名访问注解,接口添加该注解,则跳过Jwt权限验证。

/*** 自定义注解* 允许匿名访问*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowAnon {boolean required() default true;
}

3. Jwt验证拦截器


public class JwtInterceptor implements HandlerInterceptor {/*** 在请求处理之前进行调用(Controller方法调用之前)** @param request* @param response* @param handler* @return* @throws IOException*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {System.out.println("Jwt Interceptor preHandle");HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();//检查有没有允许匿名访问的注解if (method.isAnnotationPresent(AllowAnon.class)) {AllowAnon allowAnon = method.getAnnotation(AllowAnon.class);if (allowAnon.required()) {//允许匿名访问(无需权限)return true;}}String authorizationHeader = request.getHeader("Authorization");if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {ResponseErrorMessage(response);return false;}String token = authorizationHeader.substring(7);try {//验证tokenif (JwtUtil.validateToken(token)) {//验证成功return true;} else {//验证失败ResponseErrorMessage(response);return false;}} catch (Exception e) {ResponseErrorMessage(response);return false;}}/*** 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)* preHandle方法处理之后这个方法会被调用,如果控制器Controller出现了异常,则不会执行此方法** @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Jwt Interceptor postHandle");}/*** 不管有没有异常,这个afterCompletion都会被调用** @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Jwt Interceptor afterCompletion");}/*** 响应错误消息** @param response* @throws IOException*/private void ResponseErrorMessage(HttpServletResponse response) throws IOException {response.setStatus(javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED);response.setContentType("application/json; charset=UTF-8");response.getWriter().write("{\"success\":false,\"message\":\"授权失败\",\"data\":null}");}
}

4. 注册拦截器


//注册拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {/*** 重写addInterceptors()实现拦截器* 配置:要拦截的路径以及不拦截的路径** @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {System.out.println("InterceptorConfig addInterceptors");registry.addInterceptor(jwtInterceptor())  //配置拦截规则.addPathPatterns("/api/**")  // 拦截所有请求,通过判断token是否合法来决定是否需要登录.excludePathPatterns("/api/user/register"  //注册);//允许匿名访问放行的请求}@Beanpublic JwtInterceptor jwtInterceptor() {return new JwtInterceptor();}
}

5. 控制器

@RestController
@RequestMapping("/api/user")
public class UserController {/*** 注册(无需jwt验证,InterceptorConfig定义排除JwtInterceptor验证路由)** @return*/@PostMapping("register")public String register() {return "注册成功";}/*** 登录(无需jwt验证,添加AllowAnon允许匿名访问注解)** @return*/@AllowAnon@PostMapping("login")public String login() {Map<String, Object> claims = new HashMap<>();claims.put("userId", user.getId());claims.put("userName", user.getUserName());//生成tokenvar token = JwtUtil.generateToken(claims);return token;}/*** 详情(需要验证)** @return*/@GetMapping("detail")public void getUserDetail(@RequestHeader("Authorization") String token) {//获取当前用户名var username = JwtUtil.getUsername(token);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/757056.shtml

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

相关文章

图书馆管理系统 2.后台系统管理模块编写

后端 1.实体类编写 用户实体类 package jkw.pojo;import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import lombok.Data;import java.io.Serializable; import java.util.List;/*** 用户*/ Data public class …

Redis高频八股文与解决策略

什么是Redis&#xff1f; Redis是一个高性能的非关系型的键值对数据库&#xff0c;使用C编写实现的。与传统的数据库不同的是Redis是存在内存中的&#xff0c;所以读写速度非常快&#xff0c;每秒可以处理超过10万次的读写操作&#xff0c;这也是Redis常常被用作缓存的原因。 什…

Unity Toggle处理状态变化事件

Toggle处理状态变化事件&#xff0c;有两个方法。 法一、通过Inspector面板设置 实现步骤&#xff1a; 在Inspector面板中找到Toggle组件的"On Value Changed"事件。单击""按钮添加一个新的监听器。拖动一个目标对象到"None (Object)"字段&am…

研究人员发现 OpenAI ChatGPT、Google Gemini 的漏洞

自 OpenAI 推出 ChatGPT 以来&#xff0c;生成式 AI 聊天机器人的数量及其在企业中的采用率在一年多时间里呈爆炸式增长&#xff0c;但网络安全专业人士的担忧也随之增加&#xff0c;他们不仅担心威胁组织对新兴技术的使用&#xff0c;还担心大型网络的安全性及模型&#xff08…

点云预处理——滤波、旋转和平移等处理

目录 一、环境配置 二、步骤 一、环境配置 安装好ubuntu系统和ROS环境 操作系统: Ubuntu 20.04 wget http://fishros.com/install -O fishros && . fishros 二、步骤 打开终端&#xff0c;并在终端命令行输入以下指令: git clone https://gitee.com/wccworld/…

MNN Session 创建执行器(六)

系列文章目录 MNN createFromBuffer&#xff08;一&#xff09; MNN createRuntime&#xff08;二&#xff09; MNN createSession 之 Schedule&#xff08;三&#xff09; MNN createSession 之创建流水线后端&#xff08;四&#xff09; MNN Session::resize 之流水线编码&am…

MFC界面美化第三篇----自绘按钮(重绘按钮)

1.前言 最近发现读者对我的mfc美化的专栏比较感兴趣&#xff0c;因此在这里进行续写&#xff0c;这里我会计划写几个连续的篇章&#xff0c;包括对MFC按钮的美化&#xff0c;菜单栏的美化&#xff0c;标题栏的美化&#xff0c;list列表的美化&#xff0c;直到最后形成一个完整…

中小企业Java/SpringBoot体系技术抽象沉淀

目录 1. 起因 2. 参考 3.总结&#xff1a; 1. 起因 企业开发的过程中会逐渐沉淀自己的一些公共starter&方法等&#xff1b;建议可以整合开源项目与自身沉淀的一些做一个统一的parent包 2. 参考 内容参考内容框架包&#xff0c;基础core包&#xff0c;统一返回&#x…

详解Redis的持久化RDB和AOF

Redis的持久化是将内存中的数据同步到硬盘的过程 具体来说&#xff0c;Redis支持两种主要的持久化方式&#xff1a;RDB 和 AOF。 RDB&#xff08;Redis Database&#xff09; 简介 默认持久化方式 RDB会将内存中的数据快照保存到磁盘上的一个二进制文件中。这个文件包含了…

创建React+Ts项目

1.创建脚手架 create-react-app 项目名称 --template typescript 2.配置路径别名 配置路径别名---React_h5 路径别名设置-CSDN博客 3.添加组件库 npm i antd --save App.tsx 文件 引用 ant design react import React from react;import { Button } from antd;function …

NLP---Bert分词

目录&#xff1a; Q&#xff1a;bert分词步骤1&#xff1a;构建N * N 的相关性矩阵&#xff0c;计算相邻两个字的相关性&#xff0c;低的话&#xff08;<阈值&#xff09;就切割。2&#xff1a;将A词进行mask计算出A的embedding&#xff0c;然后将AB两个词一起mask&#xff…

4.线性数据结构——3.栈及例题

标准库的栈 定义&#xff1a;stack<typename> myStack;大小&#xff1a;size()压栈&#xff1a;push()弹栈&#xff1a;pop()栈顶&#xff1a;top()判空&#xff1a;empty() #include <cstdio> #include <string> #include <map> #include <algor…

视觉信息处理和FPGA实现第5次作业-Matlab实现图像逆时针旋转90度

一、Matlab2022a安装 链接&#xff1a;https://pan.quark.cn/s/6e177bc7c11d 提取码&#xff1a;dKNN 二、Matlab使用 2.1 新建一个脚本文件&#xff08;.m文件&#xff09; 2.2 另存为到便于归档的地方 考虑到.m文件如果不是全英文路径&#xff0c;也有可能会出问题&#…

Linux 服务升级:MySQL 主从(半同步复制) 平滑升级

目录 一、实验 1.环境 2.Mysql-shell 检查工具兼容性 3.逻辑备份MySQL数据 4.备份MySQL 数据目录、安装目录、配置文件 5.MySQL 升级 6.master节点 使用systemd管理mysql8 7. slave1 节点升级 8. slave2 节点升级 9.半同步设置 二、问题 1.mysqldump备份报错 2.Inn…

Docker部署dart-frog服务

参考&#xff1a; dart-frog官网&#xff1a;https://dartfrog.vgv.dev/docs/overview 使用 Dart Frog 体验 Dart 服务端开发 - 简书 打包项目 按照demo新增项目后&#xff0c;执行&#xff1a; dart_frog build 等待build后生成 build 文件夹&#xff0c;这个文件夹就是需要…

【爬虫】专栏文章索引

为了方便 快速定位 和 便于文章间的相互引用等 作为一个快速准确的导航工具 爬虫 目录&#xff1a; &#xff08;一&#xff09;web自动化和接口自动化 &#xff08;二&#xff09;实战-爬取Boss直聘信息数据

详细分析Python模块中的雪花算法(附模板)

目录 前言1. 基本知识2. 模板3. Demo 前言 分布式ID的生成推荐阅读&#xff1a;分布式ID生成方法的超详细分析&#xff08;全&#xff09; 1. 基本知识 Snowflake 算法是一种用于生成全局唯一 ID 的分布式算法&#xff0c;最初由 Twitter 设计并开源 它被设计用于解决分布式…

使用甘特图实现高效时间规划

甘特图虽然看似简单,却蕴含着规划时间的奥秘。它将复杂的工序分解成逻辑严密的任务链条,每个短小的条形图块都清晰地道出一个任务的起始、持续和终止。就像指挥家挥舞手中的棒,每个动作都精确拍着节奏,确保各个乐手分工合作、行云流水。择一个好用的甘特图制作工具,会让你事半功…

C#,图论与图算法,有向图(Graph)之环(Cycle)判断的颜色算法与源代码

1 检查该图是否包含循环 给定一个有向图,检查该图是否包含循环。如果给定的图形至少包含一个循环,则函数应返回true,否则返回false。 方法:深度优先遍历可用于检测图中的循环。连接图的DFS生成树。只有当图中存在后缘时,图中才存在循环。后边是从节点到自身(自循环)或…

Linux umount命令教程:如何安全地卸载文件系统(附实例详解和注意事项)

Linux umount命令介绍 umount命令在Linux和UNIX操作系统中用于卸载已挂载的文件系统。它通过从Linux默认文件系统的挂载点删除连接&#xff0c;使外部设备或目录不再是Linux文件系统层次结构的一部分。这个命令确保任何正在进行的文件操作都已完成&#xff0c;防止数据损坏或丢…