java后端之登录认证
- 基础登录功能:根据提供的用户名和密码判断是否存在于数据库
LoginController.java
@RestController
@Slf4j
public class LoginController {@Autowiredprivate UserService userService;@PostMapping("/login")public Result login(@RequestBody User user) {log.info("user: {}", user);User u = userService.login(user);return u != null ? Result.success(u) : Result.error("用户名或密码错误");}
}
UserController.java
@Service
public class UserServiceImpl implements com.diaryback.Service.UserService {@Autowiredprivate UserMapper userMapper;public User login(User user) {return userMapper.getUserByIdAndPassword(user);}
}
登录校验
在用户未登录情况下访问需要登录才能使用的业务,会跳转到登录界面
会话技术
- 会话:用户通过浏览器访问服务器资源时建立会话,直到一方断开连接会话结束。一次会话中可以包含多次请求和响应
- 会话跟踪:服务器需要识别多个请求是否来自同一个浏览器,以便在同一个会话的多个请求之间共享数据
Cookie
服务器端存储Cookie,响应时自动加上Cookie到客户端,客户端下次请求会自动加上cookie
不允许跨域请求
Session
Session技术基于cookie,首次访问服务端时创建session,并将sessionID附加到cookie
令牌
令牌中存储用户的身份信息以及需要共享的数据,存储在客户端
JWT令牌
jwt:JSON Web Token,将原始JSON数据进行安全封装
jwt三组成部分:
- Header:记录令牌类型,签名算法
- Payload:有效载荷,携带自定义信息,默认信息和有效期等
- Signature:签名,确保安全性。将header和payload加密计算而来
引入依赖:
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.12.3</version></dependency>
生成jwt字符串:需要指定签名算法、密钥以及自定义内容和过期时间
/*** 测试生成JWT*/@Testpublic void testGenJWT(){Map<String, Object> claims = new HashMap<>();claims.put("id", 1);claims.put("name", "maria");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "AlexandarHamiltonWeAreWaitingInTheWingsForYou")//设置加密方式和加密密钥.claims(claims)//设置自定义内容.expiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期为一个小时.compact();//生成字符串System.out.println(jwt);}
解析时需要指定签名的密钥
/*** 测试解析JWT*/@Testpublic void testParseJWT() {Claims claims = Jwts.parser().setSigningKey("AlexandarHamiltonWeAreWaitingInTheWingsForYou")//设置解密密钥.build().parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibWFyaWEiLCJpZCI6MSwiZXhwIjoxNzM3NzExMjQ3fQ.AD2hdUzHdzq9qA0ZulvOyWA857tuRUWChnEX2P1ebcI").getBody();System.out.println(claims);}
JWT工具类:jwtUtil
package com.diaryback.Utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;
import java.util.Map;public class JwtUtil {private static String signKey = "AlexandarHamiltonWeAreWaitingInTheWingsForYou";private static Long expire = 432000000L;/*** 生成jwt令牌*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return jwt;}/*** 解析jwt令牌*/public static Claims parseJwt(String jwt){Claims claims = Jwts.parser().setSigningKey(signKey).build().parseClaimsJws(jwt).getBody();return claims;}
}
Filter过滤器
可以拦截对资源的请求,通常用于登录校验、统一编码等
- 定义Filter:定义一个类,实现Filter接口,重写所有方法(init(), destroy(), doFilter())
- 配置Filter:Filter类加上@WebFilter注解,配置拦截资源的路径,同时启动类加上@ServletComponentScan开启Servlet组件支持
拦截路径的配置:
过滤器链:一个web应用中可以配置多个过滤器行程过滤器链
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;import javax.servlet.*;
import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class DemoFilter implements jakarta.servlet.Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {
// Filter.super.init(filterConfig);System.out.println("初始化过滤器");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Demo 执行过滤操作...放行前逻辑");//放行filterChain.doFilter(servletRequest, servletResponse);System.out.println("Demo 执行过滤操作...放行后逻辑");}@Overridepublic void destroy() {
// Filter.super.destroy();System.out.println("销毁过滤器");}
}
登录校验的Filter流程:
LoginFilter.java
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPObject;
import com.diaryback.Pojo.Result;
import com.diaryback.Utils.JwtUtil;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.http.HttpRequest;@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;//强制类型转换,将ServletRequest转换为其子类HttpServletRequestHttpServletResponse resp = (HttpServletResponse) servletResponse;String url = req.getRequestURL().toString();log.info("请求的url:{}", url);// 如果是登录请求则放行if(url.contains("login")){log.info("登录请求,放行");filterChain.doFilter(servletRequest, servletResponse);return;}//获取请求头中的令牌String jwt = req.getHeader("token");//判断请求头中是否有令牌if(!StringUtils.hasLength(jwt)){log.info("未登录,不允许访问");Result error = Result.error("NOT_LOGIN");//将Result转换为JSON格式传递给前端,使用fastJson包String notLogin = JSON.toJSONString(error);resp.getWriter().write(notLogin);return;}//解析token校验令牌try {JwtUtil.parseJwt(jwt);} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info("解析失败,不允许访问");Result error = Result.error("NOT_LOGIN");String notLogin = JSON.toJSONString(error);resp.getWriter().write(notLogin);return;}//放行log.info("已登录,放行");filterChain.doFilter(servletRequest, servletResponse);}
}
Interceptor拦截器
Interceptor:作用类似于Filter,拦截请求,在指定方法调用前后执行预先设定的代码
- 定义拦截器,实现HandlerInterceptor接口,并重写所有方法(preHandler, postHandle, afterCompletion)
- 注册拦截器,需要在配置类中注册
LoginCheckInterceptor.java
package com.diaryback.Interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Component //将拦截器交给Spring容器管理
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //请求处理前调用,返回false则请求不会被处理public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle执行");return true;}@Override //请求处理后调用,但在视图渲染前public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle执行");}@Override //请求处理后调用,视图渲染后public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion执行");}
}
WebConfig.java
package com.diaryback.config;import com.diaryback.Interceptor.LoginCheckInterceptor;
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 WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//添加拦截器registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");}
}
拦截路径:addPathPatterns()定义需要拦截哪些资源,excludePathPatterns()定义不需要拦截哪些资源
拦截器执行流程:
登录校验拦截器
```java
package com.diaryback.Interceptor;import com.alibaba.fastjson.JSONObject;
import com.diaryback.Pojo.Result;
import com.diaryback.Utils.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;@Slf4j
@Component //将拦截器交给Spring容器管理
public class LoginCheckInterceptor implements HandlerInterceptor {@Override //请求处理前调用,返回false则请求不会被处理public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String url = request.getRequestURL().toString();log.info("preHandle执行,url: {}", url);if(url.contains("login")){log.info("放行");return true;}String jwt = request.getHeader("token");//检查是否有令牌if(!StringUtils.hasLength(jwt)){log.info("未登录");Result error = Result.error("NOT_LOGIN");String notLogin = JSONObject.toJSONString(error);response.getWriter().write(notLogin);return false;}//解析令牌try {JwtUtil.parseJwt(jwt);} catch (Exception e) {e.printStackTrace();log.info("令牌无效");Result error = Result.error("NOT_LOGIN");String notLogin = JSONObject.toJSONString(error);response.getWriter().write(notLogin);return false;}//放行log.info("放行");return true;}@Override //请求处理后调用,但在视图渲染前public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle执行");}@Override //请求处理后调用,视图渲染后public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion执行");}
}
异常处理
定义全局异常处理器
import com.diaryback.Pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理*/
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)//指定处理的异常类型public Result ex(Exception ex){ex.printStackTrace();return Result.error("服务器异常");}
}
相关文章:

java后端之登录认证
基础登录功能:根据提供的用户名和密码判断是否存在于数据库 LoginController.java RestController Slf4j public class LoginController {Autowiredprivate UserService userService;PostMapping("/login")public Result login(RequestBody User user) {…...

【矩阵二分】力扣378. 有序矩阵中第 K 小的元素
给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。 请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素。 你必须找到一个内存复杂度优于 O(n2) 的解决方案。 示例 1࿱…...

C语言-构造数据类型
1、构造数据类型 结构体、共用体、枚举。 2、结构体 1、结构体的定义 结构体是一个自定义的复合数据类型,它允许将不同类型的数据组合在一起。 struct 结构体名 {数据类型1 成员变量1;数据类型2 成员变量2;数据类型3 成员变量3;数据类型4 成员变量4; } 2、结构体变…...
鸿蒙next 自定义日历组件
效果图预览 20250124-113957 使用说明 1.选择日期左右箭头,实现每月日历切换,示例中超出当前月份,禁止进入下一月,可在代码更改 2.日历中显示当前选择的日期,选中的日期颜色可自定义 3.日历中可展示历史记录作为数据…...

【express-generator】08-路由重定向
前言 通过前面两篇文章的讲解,我们已经介绍完第二阶段的前两点,本篇介绍第三点:路由重定向。 1. 路由重定向概述 路由重定向是指在服务器端将客户端的请求从一个 URL 重定向到另一个 URL 的过程。这通常通过 HTTP 状态码(如 30…...

搭建Spring Boot开发环境
JDK(1.8及以上版本) Apache Maven 3.6.0 修改settings.xml 设置本地仓库位置 <localRepository>D:/repository</localRepository> 设置远程仓库镜像 <mirror><id>alimaven</id><name>aliyun maven</name&…...

Spatial Group-wise Enhance (SGE) module
来源: [1905.09646] Spatial Group-wise Enhance: Improving Semantic Feature Learning in Convolutional Networks 相关工作: #GroupedFeatures #AttentionModels 创新点: 贡献: 提出了一种轻量级的SGE模块,能够…...
二叉搜索树中的搜索(力扣700)
首先介绍一下什么是二叉搜索树。 二叉搜索树是一个有序树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉…...

记录让cursor帮我给ruoyi-vue后台管理项目整合mybatis-plus
自己整合过程中会出现 work.web.exception.GlobalExceptionHandler :100 | 请求地址/admin/device/install/detail/1,发生未知异常. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.fire.mapper.DeviceInstallMapper.selectById at o…...

【可实战】Linux 系统扫盲、 Shell扫盲(如何写一个简单的shell脚本)
一、Linux系统扫盲 1.Linux 能运行主要的 UNIX 工具软件、应用程序和网络协议 2.Linux 的发行版说简单点就是将 Linux 内核与应用软件做一个打包。 目前市面上较知名的发行版有:Ubuntu、RedHat、CentOS、Debian、Fedora、SuSE、OpenSUSE、Arch Linux、SolusOS 等…...
sqlzoo答案4:SELECT within SELECT Tutorial
sql练习:SELECT within SELECT Tutorial - SQLZoo world表: namecontinentareapopulationgdpAfghanistanAsia6522302550010020343000000AlbaniaEurope28748283174112960000000AlgeriaAfrica238174137100000188681000000AndorraEurope46878115371200000…...
【fly-iot飞凡物联】(20):2025年总体规划,把物联网整套技术方案和实现并落地,完成项目开发和课程录制。
前言 fly-iot飞凡物联专栏: https://blog.csdn.net/freewebsys/category_12219758.html 1,开源项目地址进行项目开发 https://gitee.com/fly-iot/fly-iot-platform 完成项目开发,接口开发。 把相关内容总结成文档,并录制课程。…...
Lucene常用的字段类型lucene检索打分原理
在 Apache Lucene 中,Field 类是文档中存储数据的基础。不同类型的 Field 用于存储不同类型的数据(如文本、数字、二进制数据等)。以下是一些常用的 Field 类型及其底层存储结构: TextField: 用途:用于存储…...

适用于IntelliJ IDEA 2024.1.2部署Tomcat的完整方法,以及笔者踩的坑,避免高血压,保姆级教程
Tips:创建部署Tomcat直接跳转到四 一、软件准备 笔者用的是IntelliJ IDEA 2024.1.2和Tomcat 8.5。之前我使用的是Tomcat 10,但遇到了许多问题。其中一个主要问题是需要使用高于1.8版本的JDK,为此我下载了新的JDK版本,但这又引发了更多的兼容…...

XSS靶场通关详解
前言 这里作者采用phpstudy部署的xss-lab靶场,配置如下: 第一关 进入靶场后寻找页面的传参处,发现url中的name参数传了test给页面,可以在此处进行尝试xss 成功弹窗! payload: <script>alert(1)<…...

Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)
本文讲了如何在Excel中抠图头像,换背景色。 1,如何在Excel中抠图头像,换背景色 大家都知道在PS中可以很容易抠图头像,换背景色,其实Excel中也可以抠简单的图,换背景色。 ※所用头像图片为百度搜索&#x…...
备忘-humanplus相关的代码解析
-1: numpy必须为1.20.0,否则会报错,版本冲突0.rlvalue-based: 如q-learning(走迷宫),对当前状态下作出的动作进行价值计算,通过贪婪策略穷尽所有可能选择最佳state-action,但是对于连续的动作空间&#x…...

青少年编程与数学 02-008 Pyhon语言编程基础 01课题、语言概要
青少年编程与数学 02-008 Pyhon语言编程基础 01课题、语言概要 一、榜一大哥起源与早期发展版本演进与社区壮大应用领域的拓展编程语言排行榜的常客结语 二、当前排行三、出色表现四、易学易用五、特色显著六、资源丰富初学者资源中高级学习资源在线编程学习平台 课题摘要:本文…...
XSS (XSS)分类
XSS (XSS) 概要 XSS全称为Cross Site Scripting,为了和CSS分开简写为XSS,中文名为跨站脚本。该漏洞发生在用户端,是指在渲染过程中发生了不在预期过程中的JavaScript代码执行。XSS通常被用于获取Cookie、以受攻击者的…...
[Linux]el8安全配置faillock:登录失败达阈值自动锁定账户配置
前言 本篇文章的配置仅使用于el8版本的Linux,目前已在centos8、BCLinux8上验证成功,其他版本系统是否可行还得考查。 el8中管理用户登录失败锁定账户所用的模块是faillock.so,如果想要将配置应用与其他版本的Linux,建议确认Linux…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

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.…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...