Spring:强制登陆与拦截器
1.只使用session验证
(1)第一步:用户登陆时存储session
@ApiOperation("用户登陆")
@PostMapping("/login")
public AppResult login(HttpServletRequest request,@RequestParam("username") @ApiParam("用户名") @NonNull String username,@RequestParam("password") @ApiParam("用户密码") @NonNull String password) {//1.参数校验 -- 注解已完成//2.调用service层User user = userService.login(username, password);//3.设置sessionHttpSession session = request.getSession(true);session.setAttribute(AppConfig.USER_SESSION,user);return AppResult.success();
}
关键代码:
HttpServletRequest request
//3.设置sessionHttpSession session = request.getSession(true);session.setAttribute(AppConfig.USER_SESSION,user);//存储的是key-value

(2)第二步:访问接口时验获取session
@ApiOperation("查询用户信息")
@GetMapping("/info")
public AppResult<User> getUserInfo(HttpServletRequest request) {log.info("获取用户信息");User user = null;HttpSession session = request.getSession(false);if(session == null || session.getAttribute(AppConfig.USER_SESSION) == null) {//用户未登录return AppResult.failed(ResultCode.FAILED_FORBIDDEN);}user = (User) session.getAttribute(AppConfig.USER_SESSION);}if(user == null) {return AppResult.failed(ResultCode.FAILED_FORBIDDEN);}return AppResult.success(user);
}
关键代码:
HttpServletRequest request//参数
HttpSession session = request.getSession(false);
if(session == null || session.getAttribute(AppConfig.USER_SESSION) == null) {//用户未登录return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
}
只要获取不到session或者不能从session中获取到对象,就说明用户没有登陆。
上述就是只使用session进行强制用户登陆的写法,需要在每个方法都进行判断。
2.使用拦截器强制登录和session
上述是没有引入拦截器的场景,每个部分都需要引入相同的代码,就会使得代码非常的繁琐,所以我们就可以使用Spring统一功能中的拦截器。
简单介绍拦截器:由两个部分组成
第一个部分:定义拦截器(也就是指定拦截规则,比如没有session就不允许访问);第二个部分:配置拦截器,也就是执行这些规则(比如把保安投放到某某路口等)
(1)第一步:定义拦截器
语法:实现HandlerInterceptor接口,并重写其所有方法
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {log.info("LoginInterceptor ⽬标⽅法执⾏前执⾏..");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, ModelAndView modelAndView) throws Exception {log.info("LoginInterceptor ⽬标⽅法执⾏后执⾏");}@Overridepublic void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("LoginInterceptor 视图渲染完毕后执⾏,最后执⾏");}
}
其中里面有三个重写的方法,一般我们只需要重写第一个就够了,就是我们需要的拦截器
(1)preHeandle:目标方法前执行该方法(比如执行获取用户信息的方法前,会先执行该方法)。该方法返回true,后面的方法继续执行(不拦截);返回false,后面的方法中断。
(2)postHandle:目标方法执行后就会执行该方法。
(3)afterCompletion:视图渲染完毕后执行,最后执行(后端开发现在几乎不涉及视图,暂不了解)
定义拦截器:基本模版
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;@Slf4j
//把对象交给Spring管理,否则不生效
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.获取sessionHttpSession session = request.getSession(false);//2.判断是否存在session或者用户已登录if(session != null && session.getAttribute("user") != null) {//进入该方法,说明用户已登录,就不进行拦截操作return true;}//3.走到这一步,说明用户未登录,进行拦截(也可以指定跳转某一个页面)response.sendRedirect("/login.html");//设置跳转的页面,一般为登陆页面return false;//拦截并跳转}
}
上面就是配置拦截器的基本代码模版,有一个注意点:跳转的页面最好是封装成一个常量,利于后续的修改操作。
(2)第二步:配置拦截器
上面的第一步我们已经定义好了拦截规则,下面只需要配置就好(上面已经规定了哪些人员不准进入小区,接下来我们需要投放保安到小区的指定路口进行拦截)
语法:WebMvcConfigurer接口,并重写addInterceptors方法
基本模版:
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 AppInterceptorConfigurer implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;//给保安们注入拦截规则@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor)//该方法是注册,也就是执行拦截规则.addPathPatterns("/**")//该方法表示拦截所有的请求.excludePathPatterns("/login");//表示该页面不进行拦截}
}
上面就是模版,一般登录页面和注册等页面我们都是不进行拦截的,要是拦截住了就死锁了。
然后对于要拦截什么页面,看大家的需求;对于拦截器+session的介绍就结束了,也就是上面的两段代码。
3.使用令牌拦截
使用令牌技术生成一个token字符串用来验证用户是否登陆
下面是关于用户登陆和验证的基本步骤:
(1)前端发送登陆请求,后端进行验证
(2)后端验证通过,返回token
(3)客户端存储token(通过前端进行操作)
(4)客户端后续发起的请求,就会把token放在请求的header中(k-v的形式,token存储在v中)
(5)后端从header中获取到token(指定前端的k,才能获取token),进行验证
这个部分前面先介绍如何在代码中使用登陆令牌,后面再介绍代码的含义
使用步骤大致分为四步:引入依赖、编写令牌工作类、发放令牌、验证令牌
(1)第一步:引入依赖
引入pom依赖,需要使用到令牌专属的类
<!-- jwt令牌 -->
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.5</version><scope>runtime</scope>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><!-- or jjwt-gson if Gson is preferred --><version>0.11.5</version><scope>runtime</scope>
</dependency>
引入后记得刷新maven
(2)第二步:编写令牌工具utils
在主目录下创建utils包,再创建JwtUtils类
//负责生成令牌和验证令牌import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;@Slf4j
public class JwtUtils {private static long expiration = 30 * 60 * 1000; //规定令牌有效期为30分钟private static String secretString = "gaiosfhioawjfajrawrawrawrawrawrawrawrfjarawrawrawrafawfoawjfa";private static Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString));//key值,数字签名/*** 生成令牌*/public static String genJwt(Map<String, Object> data) {//生产tokenString compact = Jwts.builder()//固定方法.setClaims(data)//设置数据.setExpiration(new Date(System.currentTimeMillis()+expiration))//设置token的过期时间.signWith(key)//设置数字签名.compact();//生产tokenreturn compact;}/*** 校验令牌*/public static Claims verify(String token){//生成token用的都是同一个key,所以不需要传参//获取build对象JwtParser build = Jwts.parserBuilder().setSigningKey(key).build();Claims claims = null;try {claims = build.parseClaimsJws(token).getBody();//与token校验}catch (ExpiredJwtException e){log.error("token过期, 校验失败, token:"+ token);}catch (Exception e){log.error("token校验失败, token:"+ token);}return claims;}}
作用:这个类提供两个静态方法,第一个是负责生成令牌,第二个是负责验证令牌。
上述的生成和验证令牌属于大致模版,自己也可以进行大致的修改
(3)第三步:后端发放令牌
一般在登陆接口给用户发放令牌。
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/login")public Result login(String userName, String password){//前面一堆验证工作,这里根据自己的业务功能写//………………UserInfo userInfo = new UserInfo();//账目密码验证完成,就可以给用户发放令牌了Map<String,Object> cliams = new HashMap<>();cliams.put("id", userInfo.getId());cliams.put("name", userInfo.getUserName());//获取对应的tokenString jwt = JwtUtils.genJwt(cliams);//返回tokenreturn Result.success(jwt);}
}
在验证完用户信息后,就可以给用户设置令牌并且返回token了,token中设置的信息一般不要设置隐私信息,比如用户密码
(4)第四步:后续验证令牌
这里直接采取统一拦截器进行拦截了,下面是关于拦截规则的代码
这一步作为纯后端程序猿来说比较困难,因为要和前端的参数进行同步。前端会把token(一个字符串)以k-v的形式放入header中,所以可以从请求中进行获取
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//验证token是否合法String userToken = request.getHeader("user_token_header");log.info("从header中获取信息, token:"+ userToken);Claims claims = JwtUtils.verify(userToken);if (claims==null){//token校验失败response.setStatus(401);
// response.getOutputStream().write();
// response.setContentType();return false;}return true;}
}
user_token_header是请求头中的key,用来获取对应的value值,也就是token
相关文章:
Spring:强制登陆与拦截器
1.只使用session验证 (1)第一步:用户登陆时存储session ApiOperation("用户登陆") PostMapping("/login") public AppResult login(HttpServletRequest request,RequestParam("username") ApiParam("用…...
MySQL-数据库约束
1.约束类型 类型说明NOT NULL非空约束 指定非空约束的列不能存储NULL值 DEFAULT默认约束当没有给列赋值时使用的默认值UNIQUE唯一约束指定唯一约束的列每行数据必须有唯一的值PRIMARY KEY主键约束NOT NULL和UNIQUE的结合,可以指定一个列霍多个列,有助于…...
线性表三——队列queue
#include<bits/stdc.h> using namespace std; int n,m; queue<int> q;int main(){cin>>n>>m;for(int i1;i<n;i) q.push(i);int k0;while(!q.empty()){k;if(k<m)//从队头出来,再次回到队尾{int idq.front();//记录出去的编号 q.pop();…...
算法笔记(十)——队列+宽搜
文章目录 N 叉数的层序遍历二叉树的锯齿形层序遍历二叉树最大宽度在每个树行中找最大值 BFS是图上最基础、最重要的搜索算法之一; 每次都尝试访问同一层的节点如果同一层都访问完了,再访问下一层 BFS基本框架 void bfs(起始点) {将起始点放入队列中;标记…...
webpack配置全面讲解【完整篇】
文章目录 前言webpack 核心包:配置文件导出三种方式:在线配置 webpack配置文件解析:入口(Entry):输出(Output):加载器(Loaders):插件&…...
十、kotlin的协程
协程 基本概念定义组成挂起和恢复结构化并发协程构建器作用域构建器挂起函数阻塞与非阻塞runBlocking全局协程像守护线程 Job的生命周期 常用函数延时和等待启动和取消启动取消 暂停 协程启动调度器启动方式启动模式线程上下文继承的定义继承的公式 协程取消与超时取消挂起点取…...
vscode qt 最新开发环境配置, 基于最新插件 Qt All Extensions Pack
qt 之前发布了vscode qt offical ,但是最新更新中将其升级改为了几个不同的插件,功能更强大 1. 前置条件 qt 已安装 2. 插件安装 打开vscode 插件安装,搜索qt 会看到很多qt插件,直接选择Qt All Extensions Pack 安装 会安装qt环境所需的…...
【MySQL】Ubuntu环境下MySQL的安装与卸载
目录 1.MYSQL的安装 2.MySQL的登录 3.MYSQL的卸载 4.设置配置文件 1.MYSQL的安装 首先我们要看看我们环境里面有没有已经安装好的MySQL 我们发现是默认是没有的。 我们还可以通过下面这个命令来确认有没有mysql的安装包 首先我们得知道我们当前的系统版本是什么 lsb_…...
C# StringBuilder类:高效构建和修改字符串的利器
C# 中的 StringBuilder 类是一个可变的字符序列,用于高效地构建和修改字符串。与字符串(string)不同,字符串在 C# 中是不可变的,这意味着每次修改字符串(如拼接、替换等操作)时,都会…...
AVL平衡树(AVL Tree)
**场景:课堂讨论** --- **小明(ESFP学生)**:张老师,为什么AVL树(AVL Tree)中的旋转操作这么重要?感觉只是节点的移动,有没有什么实际意义? **张老师&#…...
【python实操】python小程序之两数取大值以及login登录
引言 python小程序之两数取大值以及login登录 文章目录 引言一、两数取大值1.1 题目1.2 代码1.3 代码解释 二、login登录2.1 题目2.2 代码2.3 代码解释 三、思考3.1 两数取大值3.2 login登录 一、两数取大值 1.1 题目 定义一个函数my_max,包含两个参数, 函数的作用…...
Pikachu-File Inclusion-远程文件包含
远程文件包含漏洞 是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在,危害性会很大。但远程文件包含漏洞的利用条件较为苛刻;因此,在web应用系统的功能设计上尽量不要让前端用户直接传变…...
TIM(Timer)定时器的原理
一、介绍 硬件定时器的工作原理基于时钟信号源提供稳定的时钟信号作为计时器的基准。计数器从预设值开始计数,每当时钟信号到达时计数器递增。当计数器达到预设值时,定时器会触发一个中断信号通知中断控制器处理相应的中断服务程序。在中断服务程序中&a…...
Microsoft Visual Studio有多油饼
#1 Microsoft Visual Studio C 2023: 必须安装在C盘 为啥? 安其他盘能亖啊? 真有病 #2 Microsoft Visual Studio C 2013: 每个硬盘必须都腾出至少8个G的空间 不是我安在这个盘不就是为了其他盘没空间吗? 合着…...
Golang | Leetcode Golang题解之第452题用最少数量的箭引爆气球
题目: 题解: func findMinArrowShots(points [][]int) int {if len(points) 0 {return 0}sort.Slice(points, func(i, j int) bool { return points[i][1] < points[j][1] })maxRight : points[0][1]ans : 1for _, p : range points {if p[0] > …...
Python 从入门到实战35(进程-multiprocessing模块)
我们的目标是:通过这一套资料学习下来,可以熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。 上篇文章我们讨论了turtle库绘制图画操作的相关知识。今天学习一下…...
“米哈游悄然布局未来科技:入股星海图,共绘具身智能机器人新篇章“
米哈游悄然入股具身智能机器人公司:技术布局与未来展望 近日,米哈游阿尔戈科技有限公司宣布入股具身智能机器人公司星海图,这一消息在行业内引起了广泛关注。米哈游,这家以游戏开发而闻名的企业,近年来正逐步扩大其在人工智能和新兴科技领域的投资布局,此次入股星海图正是…...
基于spring boot的篮球论坛系统
作者:计算机搬砖家 开发技术:SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:Java精选实战项…...
华夏ERP账号密码泄露漏洞
漏洞描述 华夏ERP账号密码泄露漏洞 漏洞复现 FOFA "jshERP-boot" POC IP/jshERP-boot/user/getAllList;.ico...
Android问题笔记五十:构建错误-AAPT2 aapt2-7.0.2-7396180-windows Daemon
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
