【Day12】登录认证、异常处理

1 登录

 先创建一个新的 controller 层:LoginController

@RestController
public class LoginController {@Autowiredprivate EmpService empService;// 注入@PostMapping("/login")public Result login(@RequestBody Emp emp) { // 包装对象Emp e = empService.login(emp);return e != null ? Result.success() : Result.error("error");}
}

在 service 层实现

service 层调用 mapper 层,mapper 层操作数据库

测试:

2 登录校验

        刚才的程序有 bug,即只要改一下 url,可以跳过登录直接进入员工管理界面,此时需要校验

2.1 会话技术

会话

        用户打开浏览器,访问 web 服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应

会话跟踪

        一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据

会话跟踪方案

  • 客户端会话跟踪技术:Cookie
  • 服务端会话跟踪技术:Session
  • 令牌技术

2.1.1 Cookie

        Cookie 是一种小型数据存储,通常存储在用户浏览器中,可以由服务器在用户访问网站时发送给用户的浏览器,并由浏览器在随后的请求中发送回服务器

2.1.2 Session

        Session 是另一种用于在用户和服务器之间保持状态的技术。与 Cookie 不同,Session 通常不直接存储在用户的浏览器中,而是存储在服务器端

2.1.3 令牌

JWT 令牌(JSON Web Token)

        定义了一种简洁的、自包含 的格式,用于在通信双方以 json 数据格式安全的传输信息。由于数字签名的存在,这些信息是可靠的

自包含:JWT 包含所有必要的信息,不需要访问服务器来验证

JWT 令牌的组成

  1. Header(头),记录令牌类型,签名算法等,例如{"alg":"HS256","type":"JWT"}
  2. Payload(有效载荷),携带一些自定义信息、默认信息等,例如{"id":"1","username":"Tom"}
  3. Signature(签名),防止 Token 被篡改、确保安全性。将 header、payload,并加入指定秘钥,通过指定签名算法计算而来

Header,Payload,Signature 字符串通过 Base64 编码变成 JWT 字符串

原理

  1. 登录成功后,生成令牌
  2. 后续每个请求,都要携带 JWT 令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理

生成 JWT 令牌

1、引入依赖——在 pom.xml 中

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

2、使用 jwts 库下的 jwt.builder() 方法

(在单元测试中写)

public void testJWT() {Map<String, Object> claim = new HashMap<>();claim.put("id", 1);claim.put("name", "wyn");String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256, "mi_yao") // JWT 第一部分 Signature签名.setClaims(claim) // JWT 第二部分 Payload载荷.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) // 设置令牌有限期为1h.compact();// 生成 JWT 令牌(字符串)System.out.println(jwt);// print// eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoid3luIiwiaWQiOjEsImV4cCI6MTcyMTM5NDcwMn0.prh9gbgvW5PTWvogGqkjPE2ofrXz-5FVGkYoDkEaNoI}}

 链式编程

.signWith()

        第一个参数是加密算法,第二个参数是密钥

.setClaims()

        设置自定义的信息,参数是 map 类型

.setExpiration()

        设置令牌有效时间

.compact()

        最终生成 JWT 令牌的字符串

(注:每次生成的令牌不一样)

JWT 的解析

@Testpublic void testParseJWT() {Map<String, Object> claims = Jwts.parser().setSigningKey("mi_yao") // 指定签名// 解析 JWS(JSON Web Signature),返回一个 JWS 对象.parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoid3luIiwiaWQiOjEsImV4cCI6MTcyMTM5NDcwMn0.prh9gbgvW5PTWvogGqkjPE2ofrXz-5FVGkYoDkEaNoI").getBody(); // 提取负载部分System.out.println(claims); // print {name=wyn, id=1, exp=1721394702}}

如果 JWT 输入不正确,就会报错

如果上面设置的 JWT 令牌有效时间过期了,也会报错

2.2 使用 JWT 令牌登录&校验

在 utils 软件包下导入一个工具类 JWTUtils:

package com.wyn.tlias.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String key = "itheima";private static Long expire = 43200000L;/*** 生成JWT令牌* @param claims JWT第二部分负载 payload 中存储的内容* @return*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, key).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return jwt;}/*** 解析JWT令牌* @param jwt JWT令牌* @return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt).getBody();return claims;}
}

2.2.1 登录

在 LoginControlller 里面直接调用 JWTUtils:

claim 信息自己添加给一个 map,然后作为一个 Result 统一响应结果返回

@RestController
public class LoginController {@Autowiredprivate EmpService empService;/*** 登录,示例 username = "jinyong",password = 123456* @param emp* @return*/@PostMapping("/login")public Result login(@RequestBody Emp emp) {Emp e = empService.login(emp);if (e != null) {Map<String, Object> claims = new HashMap<>();claims.put("id",emp.getId());claims.put("username", emp.getUsername());claims.put("name",emp.getName());
//            claims.put("password", emp.getPassword()); // 注意不要封装密码String jwt = JwtUtils.generateJwt(claims);return Result.success(jwt);}return Result.error("error");}
}

测试,返回了一个 JWT 令牌

2.2.2 校验

        现在拿到令牌,需要进行 统一拦截,如果令牌存在,就可以继续;如果没有,就返回登录页面

        统一拦截两种解决方案:

  • 过滤器 Filter
  • 拦截器 Interceptor
过滤器 Filter

        JavaWeb 三大组件(Servlet、Filter、Listener)之一

        Servlet 是一个运行在服务器端的 Java 小程序,它是 Web 应用程序的基石。Servlet 可以响应客户端的请求(通常是 HTTP 请求),并生成响应

        Filter 是一个在 Servlet 之前或之后执行的程序,用于在请求到达 Servlet 之前或响应发送给客户端之前进行预处理或后处理

        Listener 是一个监听特定事件的对象,它可以在事件发生时接收通知并执行相应的处理逻辑

        过滤器可以把对资源的请求 拦截 下来,从而实现一些特殊的功能

        过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等

使用方法

        1.定义 Filter:定义一个类,实现 Filter 接口,并重写其所有方法(就重写一个就行

        2.配置 Filter:Filter 类上加 @WebFilter 注解,配置拦截资源的路径。引导类上加@ServletcomponentScan 开启 Seflet 组件支持

        在启动类里面加上注解

@ServletComponentScan

        然后启动,发现原来的登录,发送 json 数据,已经没有响应了,被拦截(拦截了没有后续,所以没有响应),仅仅单纯拦截,而没有 放行

放行:

调用方法

filterChain.doFilter(servletRequest,servletResponse);

过滤器链

一个web应用中,可以配置多个过滤器,这多个过滤器就形成了一个过滤器链


校验

测试:

1、访问 /login,获得一个 jwt 令牌

eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpudWxsLCJpZCI6bnVsbCwidXNlcm5hbWUiOiJqaW55b25nIiwiZXhwIjoxNzIxNTE0NzI3fQ.vS6YA_M-9ptBG01ly0ELjti1QvWzs_tlqeHClhh6o-M

2、访问其他路径时,要 在请求头中携带令牌

如果不带:

携带:

拦截器 Interceptor


        拦截器是一种动态拦截方法调用的机制,类似于过滤器。是 Spring 框架中提供的,用来动态拦截控制器方法的执行
        作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码

使用方法

1、定义拦截器,实现 Handlerlnterceptor 接口,并重写其所有方法

注意加上注解 @component


 

2、注册拦截器

流程

登录校验

@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override // 目标资源方法运行前运行,返回 true 代表放行;返回 false 代表不放行// 登录校验在这里public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 注意形参直接是 HttpServletRequest 和 HttpServletResponse,不需要强制转换// 获取 url,这段可以不用写,因为在配置文件里规定了不拦截/loginString url = request.getRequestURL().toString();if (url.contains("login")){// 登录,放行return true;}// 获取令牌String jwt = request.getHeader("token");if (!StringUtils.hasLength(jwt)) {// 令牌不存在,不放行Result error = Result.error("NOT_LOGIN");String notLogin = JSONObject.toJSONString(error);response.getWriter().write(notLogin);return false;}// 验证令牌try {JwtUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();// 令牌错误,不放行Result error = Result.error("NOT_LOGIN");String notLogin = JSONObject.toJSONString(error);response.getWriter().write(notLogin);return false;}// 令牌正确,放行return true;}@Override // 目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Override // 视图渲染完毕后运行,最后运行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

 

3 异常处理

使用全局异常处理器(GlobalExceptionHandler):

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

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

相关文章

PyTorch的自动微分模块【含梯度基本数学原理详解】

文章目录 1、简介1.1、基本概念1.2、基本原理1.2.1、自动微分1.2.2、梯度1.2.3、梯度求导1.2.4、梯度下降法1.2.5、张量梯度举例 1.3、Autograd的高级功能 2、梯度基本计算2.1、单标量梯度2.2、单向量梯度的计算2.3、多标量梯度计算2.4、多向量梯度计算 3、控制梯度计算4、累计…

系统架构设计师教程(清华第二版) 第3章 信息系统基础知识-3.3 管理信息系统(MIS)-解读

系统架构设计师教程 第3章 信息系统基础知识-3.3 管理信息系统(MIS) 3.3.1 管理信息系统的概念3.3.1.1 部件组成3.3.1.2 结构分类3.3.1.2.1 开环结构3.3.1.2.2 闭环结构3.3.1.3 金字塔结构3.3.2 管理信息系统的功能3.3.3 管理信息系统的组成3.3.3.1 销售市场子系统3.3.3.2…

x86+FPGA+AI:地铁全线刷脸过闸,地铁智慧票务系统专用计算机

地铁全线刷脸过闸 | 可提供地铁智慧票务系统专用计算机 近日&#xff0c;成都地铁在全线网地铁车站正式上线“智慧票务”系统&#xff0c;全通道无接触式“戴口罩刷脸乘车”的通行方式优化了乘客出行效率、降低了疫情交叉感染风险&#xff0c;因此备受好评&#xff01; 01、地铁…

Unity UGUI 之 Image和Rawimage

本文仅作学习笔记与交流&#xff0c;不作任何商业用途 本文包括但不限于unity官方手册&#xff0c;唐老狮&#xff0c;麦扣教程知识&#xff0c;引用会标记&#xff0c;如有不足还请斧正 1.Image是什么 Unity - 手册&#xff1a;图像 精灵格式是什么&#xff1f; 1.2重要参数 …

Linux的热插拔UDEV机制和守护进程

目录 一、Linux的热插拔UDEV机制 二、守护进程 2.1 守护进程概念和基本特点&#xff1a; 2.2 显示进程信息&#xff1a; 2.3 守护进程和后台进程的区别&#xff1a; 2.4 创建守护进程的步骤和守护进程的特征&#xff1a; 2.4.1 创建守护进程的步骤&#xff1a; 2.4.2 守…

系统级联调联试方案模板

目录 系统级联调联试方案 1. 引言 2. 准备工作 3. 测试策略 4. 测试案例设计 5. 测试执行 6. 缺陷管理 7. 风险评估 8. 测试总结 9. 后续行动 10. 附录 联调联试&#xff08;Integration and Testing&#xff09;是指在系统开发过程中&#xff0c;将各个子系统或模块…

查找多个关键词在单元格出现的位置(find函数)并且统计(count函数)和显示(lookup函数)对应的关键词

目的:从交易用途中统计E列中的村名出现的次数,并且分离出村和村小组。其中F列是所有村的名称(不重复),F列是所有小组的名称 1.使用find函数查询关键词在单元格中对应的位置 在G4单元格中输入如下公式:参数解释说明: Find_text:要查找的字符串即目标字符。 Within_text …

内网隧道——隧道技术基础

文章目录 一、正向连接与反向连接1.1 正向连接1.2 反向连接 二、端口转发三、端口映射四、端口复用五、代理和隧道的区别六、常见隧道穿透分类 环境&#xff1a; kali&#xff1a;192.168.92.6&#xff0c;MSF v6.3.25 win7&#xff1a;192.168.92.7 一、正向连接与反向连接 1…

androidkiller重编译apk失败的问题

androidkiller重编译apk失败 参考&#xff1a; https://blog.csdn.net/qq_38393271/article/details/127057187 https://blog.csdn.net/hkz0704/article/details/132855098 已解决&#xff1a;“apktool” W: invalid resource directory name:XXX\res navigation 关键是编译…

【Pytorch】RNN for Name Classification

参考学习来自&#xff1a; https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.htmlRNN完成姓名分类https://download.pytorch.org/tutorial/data.zip 导入库 import glob # 用于查找符合规则的文件名 import os import unicodedata import stri…

计算机网络参考模型与5G协议

目录 OSI七层参考模型OSI模型vsTCP/IP模型TCP/IP协议族的组成 OSI七层参考模型 分层功能应用层网络服务与最终用户的一个接口表示层数据的表示,安全,压缩会话层建立,管理,终止会话传输层定义传输数据的协议端口号,以及流控和差错校验网络层进行逻辑地址寻址,实现不同网路之间的…

【QT】窗口|菜单栏|菜单项|工具栏|状态栏|浮动窗口

目录 ​编辑 QT窗口 窗口分类 菜单栏 创建菜单栏&#xff0c;菜单&#xff0c;菜单项 菜单栏 菜单 菜单项 添加分割线 添加槽函数 ​编辑 添加快捷键 工具栏 停靠位置 浮动属性 移动属性 添加快捷项 ​编辑 状态栏 ​编辑 添加标签 添加进度表 ​编辑…

TIA博途中FBD功能块图和LAD梯形图进行相互转换的具体方法示例

TIA博途中FBD功能块图和LAD梯形图进行相互转换的具体方法示例 如下图所示&#xff0c;添加一个FC块&#xff0c;编程语言选择FBD&#xff0c;简单的编写一段程序&#xff0c; 如下图所示&#xff0c;右击该FC块&#xff0c;选择属性&#xff0c;进入&#xff0c; 如下图所示&am…

python运维实战-ssh工具

1. 功能描述 1.1 系统具有的功能描述 &#xff08;1&#xff09;连接服务器&#xff1a;用户可以通过系统连接到远程服务器&#xff0c;系统支持多个服务器配置&#xff0c;并且可以方便地管理这些配置。 &#xff08;2&#xff09;执行命令&#xff1a;用户可以在连接成功后…

RabbitMQ发布确认及交换机类型

RabbitMQ发布确认机制详解 一、引言 在消息队列&#xff08;MQ&#xff09;技术中&#xff0c;RabbitMQ因其稳定性、可靠性和易用性而受到广泛欢迎。为了确保消息的可靠传递&#xff0c;RabbitMQ提供了一系列高级特性&#xff0c;其中发布确认&#xff08;Publisher Confirms&…

配置kali 的apt命令在线安装包的源为国内源

目录 一、安装VMware Tools 二、配置apt国内源 一、安装VMware Tools 点击安装 VMware Tools 后&#xff0c;会加载一个虚拟光驱&#xff0c;里面包含 VMware Tools 的安装包 鼠标右键单击 VMware Tools 的安装包&#xff0c;点击复制到 点击 主目录&#xff0c;再点击选择…

C语言 ——— 写一个函数,调整 整型数组 中 奇数偶数的顺序

目录 题目要求 代码实现 题目要求 创建一个整型数组 自定义函数实现&#xff1a;调整该数组中数字的顺序&#xff0c;使得数组中所有的奇数位于数组的前半部分&#xff0c;数组中所有的偶数位于数组的后半部分 举例&#xff1a; 输入的整型数组为&#xff1a;[234,24,45,…

TCP协议的相关特性

目录 首先先了解TCP和UDP协议的特点 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09; UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09; TCP的六个标志位 确认应答 超时重传 连接管理(三次握手,四次挥…

Python爬虫(基本流程)

1. 确定目标和范围 明确需求&#xff1a;确定你需要从哪些网站抓取哪些数据。合法性&#xff1a;检查目标网站的robots.txt文件&#xff0c;了解哪些内容可以被抓取。数据范围&#xff1a;确定爬取数据的起始和结束点&#xff0c;比如时间范围、页面数量等。 2. 选择合适的工…

科研绘图系列:R语言微生物堆积图(stacked barplot)

介绍 堆叠条形图是一种数据可视化图表,它通过将每个条形分割成多个部分来展示不同类别的数值。每个条形代表一个总体数据,而条形内的每个部分则代表该总体数据中不同子类别的数值。这种图表特别适合展示整体与部分的关系,以及各部分在整体中的比例。 特点: 多部分条形:每…