企业级SpringBoot单体项目模板 —— 使用 AOP + JWT实现登陆鉴权

  • 😜           :是江迪呀
  • ✒️本文关键词SpringBoot企业级项目模板
  • ☀️每日   一言没学会走就学跑从来都不是问题,要问问自己是不是天才,如果不是,那就要一步步来

文章目录

  • 使用JWT实现登录鉴权的流程
  • 一、AOP
    • 1.1 AOP依赖:
    • 1.2 AOP实现代码:
  • 二、JWT
    • 2.1 JWT的工作流程
    • 2.2 依赖:
    • 2.3 JWT工具类代码:
  • 三、ThreadLocal
    • 3.1 用户上下文代码:
  • 四、测试
    • 4.1 登陆生成token
    • 4.2 请求业务代码

上回我们完成了代码管理,现在终于可以也一些功能性的代码了,今天我聊一下如何使用JWT+AOP+ThreadLocal实现一个在企业中比较常用的登陆鉴权的功能。

使用JWT实现登录鉴权的流程

在这里插入图片描述

一、AOP

使用AOP拦截业务接口,来做鉴权,并将用户信息放入到ThreadLocal中去。

1.1 AOP依赖:

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

1.2 AOP实现代码:

package com.shijiangdiya.config;import com.auth0.jwt.interfaces.DecodedJWT;
import com.shijiangdiya.common.UserContent;
import com.shijiangdiya.entity.user.User;
import com.shijiangdiya.utils.JWTUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;@Aspect
@Component
public class JWTAOP {@Around("execution(* com.shijiangdiya.controller.user.*Controller.*(..))")//拦截com.shijiangdiya.controller.user文件下面的所有以Controller结尾的接口里面的所有方法。public Object interceptController(ProceedingJoinPoint joinPoint) throws Throwable {// 获取HttpServletRequestServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();// 获取JWT tokenString token = request.getHeader("token");// 解密JWT token并获取用户信息DecodedJWT decodedJWT = JWTUtil.decodeToken(token);String userId =decodedJWT.getClaim("userId").asString();String userName = decodedJWT.getClaim("userName").asString();//将用户信息放入到ThreadLocalUser user = new User();user.setId(Long.valueOf(userId));user.setName(userName);UserContent.setUserContext(user);try {// 继续处理请求return joinPoint.proceed();} finally {// 请求结束后移除ThreadLocal中的信息UserContent.removeUserContext();}}
}

这里一定要切记手动移除ThreadLocal中的值,原因是:

  • 如果你向ThreadLocal中存储了一个对象,这个对象将一直存在于ThreadLocal中,不会被垃圾回收。长时间运行的应用程序中,多次存储大量对象可能导致内存泄漏问题。
  • 某些情况下,存储在ThreadLocal中的数据可能包含敏感信息,如果不手动移除,这些信息可能被其他线程访问,导致数据泄露风险。\

这也是面试的一个问题点。

二、JWT

JWT全称为JsonWebToken,是一种无状态的,与传统的session相比它不会占用服务器的内存,在扩展安全跨平台方面要优于session。

2.1 JWT的工作流程

2.2 依赖:

   <!--引入jwt--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>

2.3 JWT工具类代码:

package com.shijiangdiya.utils;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.shijiangdiya.config.BusinessException;import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;public class JWTUtil {// 替换为自己的密钥private static final String SECRET_KEY = "shijiangdiya";/*** 生成token* @param map* @return*/public static String generateToken(Map<String, String> map) {JWTCreator.Builder builder = JWT.create();map.forEach((k, v) -> {builder.withClaim(k, v);});Calendar instance = Calendar.getInstance();instance.add(Calendar.HOUR, 1);builder.withExpiresAt(instance.getTime());return builder.sign(Algorithm.HMAC256(SECRET_KEY));}/*** 解密token* @param token* @return*/public static DecodedJWT decodeToken(String token) {try {Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);JWTVerifier verifier = JWT.require(algorithm).build();return verifier.verify(token);} catch (Exception e) {throw new BusinessException("Token验证失败!");}}
}

三、ThreadLocal

ThreadLocal是一个线程本地变量,它允许每个线程都有自己独立的变量副本。ThreadLocal通常用于在多线程环境中存储和访问线程相关的数据,以避免线程间的数据竞争和并发问题。

一般在企业级中都会使用一个UserInfo的基础类,然后需要使用到当前登录用户信息的类要继承UserInfo,这样做代码耦合度太高。而使用Threadlocal存放用户信息,就可以避免这样的情况,不需要继承可以随处可以使用,并且线程之间相互隔离,比较方便。

3.1 用户上下文代码:

package com.shijiangdiya.common;
import com.shijiangdiya.entity.user.User;
public class UserContent {private static final ThreadLocal<User> userInfo = new ThreadLocal();/*** 获取用户信息* @return*/public static User getUserContext(){return userInfo.get();}/*** 设置用户信息* @return*/public static void setUserContext(User userContext){userInfo.set(userContext);}/*** 清除用户信息* @return*/public static void removeUserContext(){userInfo.remove();}
}

四、测试

4.1 登陆生成token

切记登陆的接口要绕过AOP的拦截。

package com.shijiangdiya.controller.login;import com.shijiangdiya.config.AbstractController;
import com.shijiangdiya.config.Response;
import com.shijiangdiya.entity.user.User;
import com.shijiangdiya.model.user.LoginUserQO;
import com.shijiangdiya.service.user.IUserService;
import com.shijiangdiya.utils.JWTUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;@RestController
@RequestMapping("/user")
public class LoginController extends AbstractController {@Autowiredprivate IUserService userService;@PostMapping("/login")public Response login(@RequestBody @Valid LoginUserQO qo){//查询数据的人员信息List<User> userInfoByName = userService.getUserByName(qo.getUserName());if(CollectionUtils.isEmpty(userInfoByName)){return new Response("401","用户不存在!",null);}List<User> collect = userInfoByName.stream().filter(user -> StringUtils.equals(user.getPassword(), qo.getPassword())).collect(Collectors.toList());if(CollectionUtils.isEmpty(collect)){return new Response("401","用户密码错误!",null);}//获取tokenMap<String,String> userInfo = new HashMap<>();userInfo.put("userId",String.valueOf(collect.get(0).getId()));userInfo.put("userName",collect.get(0).getName());String token = JWTUtil.generateToken(userInfo);return new Response("200","登陆成功!",token);}
}

在这里插入图片描述

4.2 请求业务代码

package com.shijiangdiya.controller.user;import com.shijiangdiya.common.UserContent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/test1")public void test1(){Long id = UserContent.getUserContext().getId();System.out.println("用户id:"+id);String userName = UserContent.getUserContext().getName();System.out.println("用户名称:"+userName);}
}

在这里插入图片描述
控制台输出:

用户id:2
用户名称:hubayi

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

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

相关文章

【MySQL事务篇】多版本并发控制(MVCC)

多版本并发控制(MVCC) 文章目录 多版本并发控制(MVCC)1. 概述2. 快照读与当前读2.1 快照读2.2 当前读 3. MVCC实现原理之ReadView3.1 ReadView概述3.2 设计思路3.3 ReadView的规则3.4 MVCC整体操作流程 4. 举例说明4.1 READ COMMITTED隔离级别下4.2 REPEATABLE READ隔离级别下 …

四.pyqt5 登录界面和功能

一.使用qt creator 设置登录界面 主界面为之前设计的界面 from123.py 文章地址&#xff1a;三.listview或tableviw显示 二.导出ui文件为py文件 # from123.py 为导出 py文件 form.ui 为 qt creator创造的 ui 文件 pyuic5 -o x:\xxx\Fromlogin20230809.py form.ui三.python 显…

网上书店项目

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 程序运行视频查看 管理员 图书管理 添加图书 删除图书(可批量删除) 修改图书 查看图书(分页查看) 图书上下架(可批量处理) 图书推荐&#xff08;新品推荐、精品推荐&#xff0c;可批量处理&#…

关于 HTML 的一切:初学者指南

HTML 代表超文本标记语言&#xff0c;是用于创建网页和 Web 应用程序的标准语言。 本指南将全面介绍 HTML&#xff0c;涵盖从基本语法和语义到更高级功能的所有内容。 我的目标是用简单的术语解释 HTML&#xff0c;以便即使没有编码经验的人也能学习如何使用 HTML 构建网页。…

Centos7上Python克隆与对网页完整截图

有用的话谢谢点赞~ 安装Python3.11 cd /root wget https://www.python.org/ftp/python/3.11.0/Python-3.11.0.tgz tar -xzf Python-3.11.0.tgz yum -y install gcc zlib zlib-devel libffi libffi-devel yum install readline-devel yum install openssl-devel openssl11 ope…

【qemu逃逸】GACTF2020-babyqemu

前言 虚拟机用户名&#xff1a;root 无密码 设备逆向 题目去掉的符号&#xff0c;经过逆向分析&#xff0c;实例结构体如下&#xff1a; 可以看到 arr_int_8 数组后面存在一个函数指针&#xff0c;不用想基本上就是劫持该函数指针了。 denc_mmio_read 函数 这里存在越界读…

盘点苹果手机导出照片到电脑的3个方法!

大家都知道&#xff0c;手机中的照片是非常占用空间的。特别是对喜欢拍照的女生来说&#xff0c;每一张照片都很珍贵&#xff0c;并且也不舍得删除&#xff0c;所以想要将照片导出到电脑上进行保存。这样&#xff0c;也方便以后进行恢复与查看。 对于想要将苹果手机上的照片导…

英飞凌TLF35584规格书中文

官网&#xff1a; 英飞凌TLF35584QVVS2 TLF35584_SPI&#xff1a; 1 Overview2 Block Diagram3 Pin Configuration3.1 Pin Assignment - PG-VQFN-48 4 General Product Characteristics4.1 Absolute Maximum Ratings 绝对最大额定值4.2 Functional Range4.3 Thermal Resistance…

【Spring】bean的配置

文章目录 1. 前言2. name3. lazy-init4. init-method5. destroy-method6. factory-method和factory-bean 1. 前言 在之前的文章中.写到过bean的常用配置,当时只是介绍了bean标签中的常用属性配置:class,id和scope这三个属性. 不熟的小伙伴可以看一下这篇文章:【Spring】IOC容器…

利用mybatis-plus的分页插件在xml文件中联表查询实现分页(MySQL数据库)

文章目录 准备工作Mybatis-Plus分页插件配置进行分页测试domain层Controller层Service层ServiceImplMapper层分页接口测试带其他条件的分页查询 自定义的 mapper#method&#xff08;xml文件中&#xff09; 使用分页domain层Controller层Service层ServiceImplMapper层UserMapper…

在搜索引擎中屏蔽csdn

csdn是一个很好的技术博客&#xff0c;里面信息很丰富&#xff0c;我也喜欢在csdn上做技术笔记。 但是CSDN体量太大&#xff0c;文章质量良莠不齐。当在搜索引擎搜索技术问题时&#xff0c;搜索结果中CSDN的内容占比太多&#xff0c;导致难以从其他优秀的博客平台中获取信息。因…

Python机器学习算法入门教程(第三部分)

接着Python机器学习算法入门教程&#xff08;第二部分&#xff09;&#xff0c;继续展开描述。 十三、sklearn实现KNN分类算法 Pyhthon Sklearn 机器学习库提供了 neighbors 模块&#xff0c;该模块下提供了 KNN 算法的常用方法&#xff0c;如下所示&#xff1a; 类方法说明…

《国产服务器操作系统发展报告(2023)》重磅发布

11月1日&#xff0c;《国产服务器操作系统发展报告&#xff08;2023&#xff09;》&#xff08;以下简称“报告”&#xff09;在 2023 云栖大会上正式发布&#xff0c;开放原子开源基金会理事长孙文龙、中国信息通信研究院副总工程师石友康、阿里云基础软件部副总裁马涛、浪潮信…

最新版Office2024安装教程

一. 介绍&#xff1a;Office版本都是每三年发布一个版本&#xff0c;从Office 2007、2010、2013、2016、2019&#xff0c;2021到现在的2024。 二. 下载&#xff1a; http://dt1.8tupian.net/2/29913a54b1000.pg3三. 安装教程&#xff1a; 1.用到的软件是开源的脚本&#xff0c…

Docker与微服务实战——基础篇

Docker与微服务实战——基础篇 第一章 Docker 简介1.1 docker 理念1.2 容器与虚拟机比较 第二章 Docker 安装2.1 前提说明2.2 Docker的基本组成2.2.1 镜像&#xff08;image&#xff09;2.2.2 容器&#xff08;container&#xff09;2.2.3 仓库&#xff08;repository&#xff…

VLAN与配置

VLAN与配置 什么是VLAN 以最简单的形式为例。如下图&#xff0c;此时有4台主机处于同一局域网中&#xff0c;很明显这4台主机是能够直接通讯。但此时我需要让处于同一局域网中的PC3和PC4能通讯&#xff0c;PC5和PC6能通讯&#xff0c;并且PC3和PC4不能与PC5和PC6通讯。 为了实…

笔记本电脑 禁用/启用 自带键盘

现在无论办公还是生活 很多人都会选择笔记本电脑 但很多人喜欢机械键盘 或者 用一些外接键盘 但是很多时候我们想操作 会碰到笔记本原来的键盘导致错误操作 那么 我们就需要将笔记本原来的键盘禁用掉 我们先以管理员身份运行命令窗口 然后 有两个命令 禁用默认键盘 sc conf…

你犯过程序员容易犯的这些错误吗?快来看看!

一、前言 写了20多年代码&#xff0c;我见过不下于4位数的程序员&#xff0c;我觉得程序员的能力水平可以分为4个阶段&#xff1a;线性级、逻辑级、架构级和工程级。 同样的在这些人当中&#xff0c;我也发现了8个程序员最常见的陋习&#xff0c;基本上可以覆盖90%的人&#…

GPT学习笔记

百度的文心一言 阿里的通义千问 通过GPT能力&#xff0c;提升用户体验和产品力 GPT的出现是AI的iPhone时刻。2007年1月9日&#xff0c;第一代iPhone发布&#xff0c;开启移动互联网时代。新一轮的产业革命。 GPT模型发展时间线&#xff1a; Copilot - 副驾驶 应用&#xf…

大数据毕业设计选题推荐-家具公司运营数据分析平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…