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和各种游戏开发技巧,以及各种资源分…...
Qt C++ 集成 SQLite 实现本地数据持久化:从原理到宠物投喂器实战
1. 项目概述与核心需求解析最近在做一个宠物智能投喂器的数据管理后台,核心需求是把设备上传的各种运行数据持久化存储起来,方便后续分析和查看。设备会上传投喂间隔时间、水温、剩余重量这几个关键参数,我需要一个轻量、可靠且易于集成的本地…...
保姆级教程:用YOLOv5 v6.0训练自己的数据集(从环境配置到模型导出)
从零构建工业级YOLOv5 v6.0检测系统:环境配置到模型部署全流程实战 在工业质检、安防监控等场景中,快速构建高精度目标检测系统已成为工程师的核心竞争力。YOLOv5以其卓越的平衡性——兼顾速度与精度、完善的工程化支持,成为落地首选。本文将…...
Jable视频下载神器:3分钟掌握Chrome插件+本地下载器完美方案
Jable视频下载神器:3分钟掌握Chrome插件本地下载器完美方案 【免费下载链接】jable-download 方便下载jable的小工具 项目地址: https://gitcode.com/gh_mirrors/ja/jable-download 还在为无法保存Jable.tv上的精彩视频而烦恼吗?想要轻松将喜欢的…...
RT-Thread开发者大会技术解析:从RTOS内核到AIoT平台实战指南
1. 项目概述:一场国产嵌入式技术的年度盛会 2021年的RT-Thread开发者大会,对于当时国内嵌入式软件圈的从业者来说,绝对是一个绕不开的关键节点。那一年,整个行业正处在一个微妙的转折期:一方面,芯片供应链…...
基于YOLO+DeepSeek的病虫害检测与环境监测一体化解决方案
智慧农业智能云平台 定位:基于YOLODeepSeek的病虫害检测与环境监测一体化解决方案🌾 核心识别能力 • 支持作物:9种 作物 作物 作物 🌽 玉米 🌾 小麦 🌾 水稻 🍅 番茄 🥔 马铃薯 &am…...
Perplexity vs ChatGPT vs Claude:用户评论情感分析对比报告(NLP模型实测,含21项维度打分)
更多请点击: https://intelliparadigm.com 第一章:Perplexity用户评论汇总 主流平台用户反馈概览 Perplexity 作为以引用驱动、实时联网为特色的AI问答工具,近期在Reddit、Product Hunt及Twitter等平台收获大量真实用户评论。高频关键词包括…...
影像技术实战11:视频封面生成黑屏、模糊、重复?FFmpeg + OpenCV 构建高质量缩略图自动优选方案
影像技术实战11:视频封面生成黑屏、模糊、重复?FFmpeg OpenCV 构建高质量缩略图自动优选方案 一、问题场景:封面不是“随便截一帧” 在视频平台、素材管理系统、内容审核后台、AI 剪辑工具里,视频上传后自动生成封面是一个很常见…...
YOLOv8铁轨轨道缺陷识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置)
摘要 针对铁轨表面缺陷自动化检测需求,本研究构建了基于YOLOv8的实时检测系统,涵盖Spalling(剥落)、Wheel Burn(车轮烧伤)、Squat(轨头压溃)和Corrugation(波浪磨耗&…...
LinkSwift网盘直链助手:让你的下载体验更简单高效
LinkSwift网盘直链助手:让你的下载体验更简单高效 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘…...
从U盘到高端SSD:一文搞懂FTL映射表(块/页/混合)的演进与实战选择
从U盘到高端SSD:一文搞懂FTL映射表(块/页/混合)的演进与实战选择 存储设备的性能差异往往隐藏在底层算法的设计哲学中。当你在电商平台对比两款SSD时,是否思考过为什么同样标称1TB容量的产品,价格能相差数倍ÿ…...
