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和各种游戏开发技巧,以及各种资源分…...
H3C F1070防火墙console密码恢复实战指南
1. 当console密码成为拦路虎时 刚接手公司网络设备那会儿,我就被H3C F1070防火墙来了个下马威。那天机房搬迁后需要调试设备,结果发现前任管理员留下的console密码早已失效。这种场景就像你拿着钥匙回老家,却发现锁芯被换了一样尴尬。作为网络…...
SillyTavern角色卡片系统全解析:从技术原理到实战应用
SillyTavern角色卡片系统全解析:从技术原理到实战应用 【免费下载链接】SillyTavern LLM Frontend for Power Users. 项目地址: https://gitcode.com/GitHub_Trending/si/SillyTavern 技术原理:PNG元数据驱动的角色存储机制 SillyTavern角色卡片…...
Qwen3-ASR-0.6B开发者案例:集成至CRM系统实现通话内容自动归档
Qwen3-ASR-0.6B开发者案例:集成至CRM系统实现通话内容自动归档 1. 项目背景与需求场景 在现代企业客户关系管理(CRM)系统中,通话录音是宝贵的业务数据资源。销售团队的客户沟通、客服中心的问题解决、业务洽谈的重要细节——所有…...
Pi0 Web演示服务监控:Prometheus+Grafana指标采集与告警配置
Pi0 Web演示服务监控:PrometheusGrafana指标采集与告警配置 1. 项目概述与监控需求 Pi0作为一个先进的视觉-语言-动作流机器人控制模型,其Web演示服务的稳定运行对于用户体验和开发测试至关重要。在生产环境中,我们需要实时掌握服务的运行状…...
国产MCU实战:华大HC32F460串口DMA+超时中断,替代STM32空闲中断的完整配置流程
国产MCU实战:华大HC32F460串口DMA超时中断的工程化实现指南 在嵌入式开发领域,国产MCU的崛起为开发者提供了更多选择。华大半导体的HC32F460系列以其出色的性能和灵活的配置,成为许多项目中替代STM32的理想选择。本文将深入探讨如何在这款芯片…...
C++ vcpkg:安装、使用、原理与选型
C vcpkg:安装、使用、原理与选型 vcpkg 是微软与社区维护的开源 C/C 包管理器,目标是统一第三方库的获取、构建与集成流程。它支持 Windows / Linux / macOS,并与 CMake、Visual Studio 等工具链深度协作。本文覆盖:是什么、如何…...
VCAM虚拟摄像头:革新移动设备视觉交互的技术探索
VCAM虚拟摄像头:革新移动设备视觉交互的技术探索 【免费下载链接】com.example.vcam 虚拟摄像头 virtual camera 项目地址: https://gitcode.com/gh_mirrors/co/com.example.vcam VCAM虚拟摄像头是一款基于Xposed框架的安卓应用,通过HOOK技术&…...
Windows 11终极优化指南:用Win11Debloat免费提升51%系统性能
Windows 11终极优化指南:用Win11Debloat免费提升51%系统性能 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本,用于从Windows中移除预装的无用软件,禁用遥测,从Windows搜索中移除Bing,以及执行各种其他更改以简…...
ChatGPT、Claude、Gemini大模型实战对比:哪个更适合你的业务场景?
ChatGPT、Claude、Gemini大模型实战对比:哪个更适合你的业务场景? 当企业面临AI大模型选型时,往往陷入技术参数的海洋却难以找到业务适配的答案。本文将从真实业务需求出发,通过客服对话、内容创作、数据分析三个典型场景的实测数…...
别再折腾CUDA了!用Anaconda在Windows上一键搞定TensorFlow 2.5 GPU环境(附清华源配置)
告别CUDA版本地狱:Anaconda三分钟部署TensorFlow GPU全攻略 刚接触深度学习的开发者们,往往在第一步就被GPU环境配置劝退。CUDA与cuDNN的版本匹配问题像一道高墙,让无数Windows用户在TensorFlow门前徘徊。我曾见过同事花三天时间反复卸载重装…...
