[Java]SpringBoot登录认证流程详解

登录认证

登录接口

1.查看原型

2.查看接口

3.思路分析

登录核心就是根据用户名和密码查询用户信息,存在则登录成功, 不存在则登录失败

4.Controller

@Slf4j
@RestController
public class LoginController {@Autowiredprivate EmpService empService;/*** 登录的方法** @param emp* @return*/@PostMapping("/login")public Result login(@RequestBody Emp emp) {log.info("员工登录:{}", emp);Emp e = empService.login(emp);return e != null ? Result.sucess():Result.error("用户名或密码错误");}
}

5.Server

/*** 员工管理*/
public interface EmpService {/*** 员工登录* @param emp*/Emp login(Emp emp);
}
@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;/*** 员工登录* @param emp* @return*/@Overridepublic Emp login(Emp emp) {return empMapper.getByUsernameAndPassword(emp);}
}

6.Mapper

/*** 员工管理*/
@Mapper
public interface EmpMapper {/*** 根据用户名和密码查询账户信息* @param emp* @return*/@Select("select * from emp where username = #{username} and password = #{password}")Emp getByUsernameAndPassword(Emp emp);}

7.接口测试

登录校验

前端的所有请求, 都需要经过登录判断, 登录了进行正常操作, 没登录则返回错误信息, 让用户去登录页

会话跟踪

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

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

Cookie

客户端会话跟踪技术

  1. 优点:
  • HTTP协议支持的技术
  • 服务器返回Cookie / 浏览器保存Cookie / 客户端携带Cookie 都是自动完成的
  1. 缺点:
  • 移动端APP无法使用Cookie
  • 不安全, 用户可以自己禁用Cookie

  • Cookie不能跨域
  1. 当前地址和请求地址的 协议, 域名和端口 出现不同, 就形成了跨域

示例

@Slf4j
@RestController
public class SessionController {//设置Cookie@GetMapping("/c1")  public Result cookie(HttpServletResponse response){//通过HttpServletResponse获取响应对象//设置Cookit的name和valueresponse.addCookie(new Cookie("login_username","itheima")); return Result.success();}//获取Cookie@GetMapping("/c2")public Result cookie2(HttpServletRequest request){//获取所有的CookieCookie[] cookies = request.getCookies();  for (Cookie cookie : cookies) {if(cookie.getName().equals("login_username")) {  //找到name为login_username的CookieSystem.out.println("login_username:" + cookie.getValue());}}return Result.success();}
}
  1. 后端只要设置了cookie, hppt就会自动在响应头的Set-Cookie属性中携带cookie信息

  1. 浏览器解析http时, 如果发现了Set-Cookie信息, 就会把信息自动储存在本地

  1. 当下次请求时, 就会在请求头的Cookie属性中自动携带该cookie信息

Session

服务端会话跟踪技术

  1. Session是基于Cookie实现的
  • Cooike直接把数据存储在浏览器, 不安全
  • Session是把Seeion ID存在在浏览器, 数据存储在服务器
  1. 优点: 数据存储在服务端, 安全
  2. 缺点:
  • Session基于Cookie实现,也继承了其缺点
  • 服务器集群环境下无法直接使用Session

示例

@Slf4j
@RestController
public class SessionController {// 往HttpSession中存储值@GetMapping("/s1")public Result session1(HttpSession session) {log.info("HttpSession-s1:{}", session.hashCode());//往session中存储值session.setAttribute("loginUser", "tom");  return Result.success();}// 从HttpSession中获取值@GetMapping("/s2")public Result session2(HttpServletRequest request) {HttpSession session = request.getSession();log.info("HttpSession-s2:{}", session.hashCode());//从session中获取数据Object loginUser = session.getAttribute("loginUser");  log.info("loginUser:{}", loginUser);return Result.success(loginUser);}
}
  1. 后端只要设置了Session, hppt就会自动在响应头的Set-Cookie属性中携带Session ID信息

  1. 浏览器解析http时, 如果发现了Set-Cookie信息, 就会把信息自动储存在本地

  1. 当下次请求时, 就会在请求头的Cookie属性中自动携带该Session ID信息

JWT令牌

介绍

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

  1. 官网: JSON Web Tokens - jwt.io
  2. 执行流程
  • 登录成功后, 生成令牌, 响应给前端, 前端保存起来
  • 前端的后续请求, 都携带JWT令牌
  • 后端在处理请求之前, 先校验令牌, 再处理业务
  1. 优缺点
  • 支持PC/移动端/小程序
  • 解决集群环境下的认证问题
  • 减轻服务器存储压力
  • 需要自己实现

JWT令牌本质是JSON对象, JSON对象储存数据, 经过Base64编码后, 在拼接上数字签名就形成了JWT令牌

  1. Base64: 是一种基于64个可打印字符(A-Z a-z 0-9 + /) 来表示二进制数据的编码方式
生成与校验
// JWT依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
@Test
public void testGenJwt(){Map<String,Object> claims = new HashMap<>();claims.put("id",1);claims.put("name","tom");// 生成JWT令牌String jwt = Jwts.builder().signWith(SignatureAlgorithm.HS256,"itheima")  //指定签名算法.setClaims(claims)  //自定义内容(载荷).setExpiration(new Date(System.currentTimeMillis()+3600*1000))  //设置有效期为1H.compact();System.out.println(jwt);
}
@Test
public void testParseJWT(){// 解析JWT令牌Claims claims = Jwts.parser().setSigningKey("itheima").parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTY5NjE0OTc2Nn0.7-rlCqZQ1XssTdNOM2os0s-mpuKHzUkwFWtsvMOlalY").getBody();System.out.println(claims);
}
  1. JWT校验时使用的签名秘钥, 必须和生成JWT令牌时使用的秘钥配套
  2. 如果JWT令牌解析时报错, 说明JWT令牌被篡改 或者 失效了
登录校验-下发令牌

引入jwt依赖

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

引入jwt工具类

public class JwtUtils {//指定签名秘钥private static String signKey = "itheima";//指定过期时间(12h)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, signKey).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(signKey).parseClaimsJws(jwt).getBody();return claims;}
}

生成jwt令牌, 并返回给前端

@Slf4j
@RestController
public class LoginController {@Autowiredprivate EmpService empService;/*** 登录的方法** @param emp* @return*/@PostMapping("/login")public Result login(@RequestBody Emp emp) {log.info("员工登录:{}", emp);Emp e = empService.login(emp);//登录成功,生成jwt令牌,并下发令牌if(e!=null) {//把用户信息存入Map集合Map<String,Object> claims = new HashMap<>();claims.put("id",e.getId());claims.put("name",e.getName());claims.put("username",e.getUsername());//生成jwt令牌String jwt = JwtUtils.generateJwt(claims); //jwt令牌包含了用户信息// 下发令牌return Result.success(jwt);}//登录失败,返回错误信息return Result.error("用户名或密码错误");}
}

接口测试

过滤器

快速入门

filter过滤器是 javaWeb 三大组件( Servler / Filter / Listener )之一

  1. 过滤器可以拦截请求, 从而实现特殊功能
  2. 过滤器一般完成一些通用操作, 比如登录校验, 统一编码处理, 敏感字处理等

定义过滤器: 定义一个类, 实现Filter接口, 重写其所有方法

// 设置拦截请求的路径
@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException {//初始化的方法,服务器启动时只调用一次System.out.println("服务器启动了");Filter.super.init(filterConfig);}@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 拦截到请求之后调用,调用多次System.out.println("拦截到请求了");// 设置放行, 不放行前端拿不到响应结果filterChain.doFilter(servletRequest,servletResponse);// 放行后的代码执行完, 还会回到拦截器System.out.println("放行后的逻辑");}@Override public void destroy() {//销毁的方法,服务器关闭时只调用一次System.out.println("服务器关闭了");Filter.super.destroy();}
}
  1. 注意Filter是 javax.servlet 下的包
  2. 实际业务中, init 方法和 destroy方法不需要重写, 使用默认实现即可

配置过滤器: 过滤器是JavaWeb组件, 不是Springboot组件, 所以需在再启动类进行配置, 才能生效

//开启对servlet组件的支持
@ServletComponentScan 
@SpringBootApplication
public class TliasWebManagementApplication {public static void main(String[] args) {SpringApplication.run(TliasWebManagementApplication.class, args);}}
详解

拦截器的执行流程

  1. 请求被拦截后, 先执行放行前的逻辑, 符合条件放行
  2. 方形后访问资源, 资源访问完成后还会回到过滤器中
  3. 回到过滤器后, 会执行过滤器放行后的逻辑

根据需求, 设置过滤器器的拦截路径

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

  1. 顺序: 定义多个过滤器之后, 过滤器生效的优先级, 是按照过滤器类名(字符串)的自然排序
登录校验-Filter

使用过滤器完成前端请求的登录校验

  1. 除了登录请求, 所有的请求都要进行令牌校验
  2. 拦截请求之后, token存在并且通过校验, 才能继续访问资源, 否则返回登录错误

登录校验实现的步骤

// 登录校验过滤器
@Slf4j
@WebFilter(urlPatterns = "/*")
public class loginCheckFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;// 1,获取urlString url = req.getRequestURI().toString();log.info("请求到的url: {}", url);// 2,判断url是否包含'login'if (url.contains("login")) {log.info("登录操作, 放行...");chain.doFilter(request, response);return;}// 3, 获取请求头中的tokenString jwt = req.getHeader("token");// 4, 判断令牌是否存在// 使用springframework提供的工具类if (!StringUtils.hasLength(jwt)) {log.info("请求头token为空");Result error = Result.error("NOT_LOGIN");// 手动转换 把 对象-> JSON  ------->使用阿里巴巴fastJSON插件String notLogin = JSON.toJSONString(error);resp.getWriter().write(notLogin);return;}// 5, 解析tokentry {JwtUtils.parseJWT(jwt);} catch (Exception e) {e.printStackTrace();// 解释失败log.info("解释令牌失败");Result error = Result.error("NOT_LOGIN");String notLogin = JSON.toJSONString(error);resp.getWriter().write(notLogin);return;}// 6, 放行log.info("令牌合法, 放行");chain.doFilter(request, response);}
}
  1. 在springbott中, 响应的数据会被自动封装为JSON对象
  2. 在过滤器中, 我们要手动把数据转成JSON, 才能响应给前端
// fastjson依赖
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version>
</dependency>

接口测试

拦截器

快速入门

定义拦截器: 实现HandlerIntereptor接口, 并重写其所有方法

@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override  //目标资源方法运行前运行, 返回true放行,反回false不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {System.out.println("目标资源方法运行前运行");return true;}@Override //目标资源方法运行后运行public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("目标资源方法运行后");}@Override //视图渲染完毕后运行,最后运行public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("视图渲染完毕后");}
}
  1. 拦截器的所有方法都有默认实现, 定义拦截器时按需实现接口的方法即可

注册拦截器

@Configuration  //标明配置类
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册拦截器,并指定监听路径registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**")}
}
详解

配置拦截路径: 拦截器可以根据需求, 配置不同的拦截路径

拦截器的执行流程

过滤器和拦截器的区别

登录校验-Interceptor

使用拦截器完成登录校验, 登录校验的代码的逻辑是不变的, 只是放行方式不同

@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {@Override  //目标资源方法运行前运行, 返回true放行,反回false不放行public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {//1,获取请求URLString url = req.getRequestURL().toString();log.info("请求的URL:{}", url);//2,判断是否包含login,登录操作直接放行if (url.contains("login")) {log.info("登录操作,放行");return true;}//3,获取请求头的令牌String jwt = req.getHeader("token");//4,判断令牌是否存在,如果不存在返回错误信息if (!StringUtils.hasLength(jwt)) {log.info("请求头token信息为空");// 创建错误对象Result error = Result.error("NOT_LOGIN");// 手动转换 对象->JSONString notLogin = JSONObject.toJSONString(error);// 响应数据resp.getWriter().write(notLogin);// 阻止代码继续往下执行return false;}//5,解析token,如果解析失败则token无效try {JwtUtils.parseJWT(jwt);} catch (Exception e) {// 输出错误日志e.printStackTrace();log.info("解析令牌失败,返回错误信息");// 创建错误对象Result error = Result.error("NOT_LOGIN");// 手动转换 对象->JSONString notLogin = JSONObject.toJSONString(error);// 响应数据resp.getWriter().write(notLogin);// 阻止代码继续往下执行return false;}//6,token合法,放行log.info("token合法,放行");return true;}
}
@Configuration  //标明配置类
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册拦截器,并指定监听路径,排除监听路径registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");}
}

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

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

相关文章

数仓基础(七):离线与实时数仓区别和建设思路

文章目录 离线与实时数仓区别和建设思路 一、离线数仓与实时数仓区别 二、实时数仓建设思路 离线与实时数仓区别和建设思路 一、离线数仓与实时数仓区别 离线数据与实时数仓区别如下&#xff1a; 对比方面 离线数仓 实时数仓 架构选择 传统大数据架构 Kappa架构 建设…

数据结构(Java)实现:栈和队列

文章目录 1. 栈的模拟实现1.1 普通栈的模拟实现1.2 泛型栈的模拟实现 2. 栈的介绍3. 栈的使用4. 栈的应用场景4.1 改变元素的序列4.2 将递归转换为循环4.3 使用栈解题 5. 栈的链表实现6. 队列概念7. 队列的使用8. 模拟队列的实现8.1 链式队列8.2 顺序队列 9. 双端队列 1. 栈的模…

Python编码系列—Python中的安全密码存储与验证:实战指南

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

livox MID-360调试(解决ip设置问题)

整体的调试思路参考大疆Livox Mid360 使用指南_mid360中的imu内参-CSDN博客这篇博客。 但是在调试过程中出现了ip地址设置不对导致的报错&#xff1a; 1.livox viewer中看不到点云数据 2.livox SDK2 bind error。 joeyjoey:~/slam/Livox-SDK2/build/samples/livox_lidar_qu…

基于PLC的电热水器的水箱水位控制系统(论文+源码)

1总体方案设计 本设计基于PLC的电热水器的水箱水位控制系统的整体结构如图2.1所示&#xff0c;系统采用S7-1200 PLC为控制器&#xff0c;可以实现电热水器水箱中的水位、水温检测&#xff0c;并且用户可以设定目标水位和水温&#xff0c;在自动模式下&#xff0c;当水位低于低水…

mysql 8.0 的 建表 和八种 建表引擎实例

文章目录 MySQL 8.0 中&#xff0c;主要有以下四种常见的建表引擎一、InnoDB 引擎建表注意点建表知识点 二、MyISAM 引擎建表使用场景 三、Memory 引擎使用场景 四、Archive 引擎五、BLACKHOLE 引擎一、特点二、适用场景三、注意事项 六、MRG_MyISAM 引擎MRG_MyISAM 和 MyISAM …

uniapp组件中的emit声明触发事件

emit解析 在 uniapp 中&#xff0c;emit 主要用于组件间通信&#xff0c;特别是在子组件需要向父组件或者其他组件发送消息的时候。具体用途包括&#xff1a; 子传父数据&#xff1a;子组件通过 $emit 触发一个事件&#xff0c;并携带参数&#xff0c;父组件监听这个事件并对参…

Oracle 网络安全产品安全认证检索

自2023年7月1日起&#xff0c;国家网信办、工业和信息化部、公安部、国家认证认可监督管理委员会统一公布和更新网络关键设备和网络安全专用产品清单。列入《网络关键设备和网络安全专用产品目录》的网络安全专用产品应当按照《信息安全技术网络安全专用产品安全技术要求》等相…

笔记:应用Visual Studio Profiler分析CPU使用情况

一、目的&#xff1a;应用Visual Studio Profiler分析CPU使用情况 使用 Visual Studio Profiler 分析 CPU 使用情况可以帮助你识别性能瓶颈&#xff0c;优化代码&#xff0c;提高应用程序的响应速度。 二、实现 以下是如何使用 Visual Studio Profiler 分析 CPU 使用情况的详…

保存json时,保存成自己喜欢的格式的方法(而不是直接保存成格式化的json文档)

保存json时&#xff0c;不是直接保存成格式化的json文档的格式的方法 前言&#xff0c;博主是如何把格式话的json格式保存成自己喜欢的json格式的保存成格式化的json文档的格式&#xff1a;带缩进格式全部保存成一行每条数据保存成一行&#xff1a; 保存成自己喜欢的格式碎碎念…

Hadoop之HDFS的原理和常用命令及API(java)

1、简介 书接上回&#xff0c;上篇博文中介绍如何安装Hadoop和基本配置&#xff0c;本文介绍Hadoop中分布式文件组件--HDFS&#xff0c;在HDFS中&#xff0c;有namenode、datanode、secondnamenode这三个角色&#xff0c;本文将详细介绍这几个组件是如何进行协作的&#xff0c;…

【数据结构 | 每日一题】图的概念辨析

图的概念辨析 考点分析&#xff1a;我们学习数据结构图的第一小节就是&#xff1a;图的基本概念&#xff0c;我们会发现图的概念非常多且有些概念之间又很像&#xff0c;而对于初学者来说&#xff0c;相比树的概念是不好理解的&#xff0c;很容易搞混&#xff0c;因此做了这么…

传输层(TCP、UDP、RDT详解)

目录 1.无连接传输&#xff1a;UDP UDP&#xff1a;User Datagram Protocol&#xff08;用户数据报协议&#xff09; UDP&#xff1a;校验和 Internet校验和的例子 2.可靠数据传输&#xff08;Rdt&#xff09;的原理 可靠数据传输&#xff1a;问题描述 1.Rdt1.0&#xff…

【hot100篇-python刷题记录】【在排序数组中查找元素的第一个和最后一个位置】

R7-二分查找篇 目录 双指针 二分优化 ps: 思路&#xff1a; 双指针 直接用双指针回缩啊 class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:ret[-1,-1]left,right0,len(nums)-1while left<len(nums):if nums[left]target:ret[0]…

华为Huawei路由器交换机SSH配置

华为设备的SSH登录配置需要5个步骤&#xff0c;示例如下&#xff1a; 一、配置命令 使能SSH功能 stelnet server enable生成公钥 rsa local-key-pair create 1024配置AAA用户密码及相应授权 aaalocal-user xxx password cipher xxxyyy1234local-user xxx privilege level …

三十二、初识Gin框架

目录 一、搭建web项目 1、引入gin依赖 2、搭建项目结构 二、路由绑定 1、创建路由 解释&#xff1a; 2、创建实例化模块 3、创建具体事项 4、main中添加注册 一、搭建web项目 1、引入gin依赖 在项目路径下&#xff0c;终端中输入 go get -u github.com/gin-gonic/gin…

语音测试(一)视频转音频

视频转音频 下载ffmpeg工具进入bin目录cmd进入控制台输入命令 ffmpeg.exe -i ./视频.mp4 ./音频.wav

C语言试题(含答案解析)

单选 1.下面C程序的运行结果为&#xff08;&#xff09; int main(void) {printf("%d", B < A);return 0; }A.编译错误 B.1 C.0 D.运行错误 A’的ascii码值为65&#xff0c;‘B’的ascii码值为66&#xff0c;‘B’<‘A’是不成立的&#xff0c;返回0&#xf…

什么是W外链?外链的优势有哪些?

一、定义 定义W 外链是一家企业级在线短链接生成工具&#xff0c;免费的微信获客助手&#xff0c;支持批量短链接网址生成等&#xff0c;还支持自定义域名短链接数据统计等。在链接缩短的同时&#xff0c;支持高并发、防劫持&#xff0c;是专业的在线生成短链接工具。 网络营…

PrimeTime low power-多电压设计流程(3)

4.Golden UPF flow Golden UPF flow是维护设计多电压电源意图的可选方法。它在整个综合、物理实现和验证步骤中使用原始的Golden UPF 文件,以及由综合和物理实现工具生成的supplemental UPF 文件。 图 141 比较了传统的 UPF-prime 流程与Golden UPF 流程。 Golden UPF 流程在…