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("服务器异常");}
}

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

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

相关文章

基于SpringBoot的网上考试系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Elastic Agent 对 Kafka 的新输出:数据收集和流式传输的无限可能性

作者&#xff1a;来 Elastic Valerio Arvizzigno, Geetha Anne 及 Jeremy Hogan 介绍 Elastic Agent 的新功能&#xff1a;原生输出到 Kafka。借助这一最新功能&#xff0c;Elastic 用户现在可以轻松地将数据路由到 Kafka 集群&#xff0c;从而实现数据流和处理中无与伦比的可扩…

【ROS2】RViz2界面类 VisualizationFrame 详解

1、简述 VisualizationFrame 继承自 QMainWindow 和 WindowManagerInterface; 窗口顶部是常规布局:菜单栏 和 工具栏 窗口中心是 RenderPanel,用来渲染3D画面 周围是dock区域,包括:DisplaysPanel、ViewsPanel、TimePanel、SelectionPanel 和 ToolPropertiesPanel Windo…

poi在word中打开本地文件

poi版本 5.2.0 方法1&#xff1a;使用XWPFFieldRun&#xff08;推荐&#xff09; 比如打开当前相对路径的aaaaa.docx XWPFFieldRun run paragraph.createFieldRun();CTRPr ctrPr run.getCTR().addNewRPr();CTFonts font ctrPr.addNewRFonts();// 设置字体font.setAscii(&quo…

PCIE模式配置

对于VU系列FPGA&#xff0c;当DMA/Bridge Subsystem for PCI Express IP配置为Bridge模式时&#xff0c;等同于K7系列中的AXI Memory Mapped To PCI Express IP。

【Uniapp-Vue3】request各种不同类型的参数详解

一、参数携带 我们调用该接口的时候需要传入type参数。 第一种 路径名称?参数名1参数值1&参数名2参数值2 第二种 uni.request({ url:"请求路径", data:{ 参数名:参数值 } }) 二、请求方式 常用的有get&#xff0c;post和put 三种&#xff0c;默认是get请求。…

4070s显卡部署Deepseek R1

电脑配置&#xff1a; 处理器&#xff1a;AMD 7950X 内存&#xff1a;32G 硬盘&#xff1a;致态tiplus7100 2t 显卡&#xff1a;4070 super 12G 部署方法&#xff1a; 1. 到ollama官网下载安装ollama https://ollama.com/https://ollama.com/https://ollama.com/https://…

工业相机 SDK 二次开发-Sherlock插件

本文介绍了 sherlock 连接相机时的插件使用。通过本套插件可连接海康的工业相机。 一&#xff0e;环境配置 1. 拷贝动态库 在用户安装 MVS 目录下按照如下路径 Development\ThirdPartyPlatformAdapter 找到目 录为 DalsaSherlock 的文件夹&#xff0c;根据 Sherlock 版本找到…

three.js+WebGL踩坑经验合集(4.1):THREE.Line2的射线检测问题(注意本篇说的是Line2,同样也不是阈值方面的问题)

上篇大家消化得如何了&#xff1f; 笔者说过&#xff0c;1级编号不同的两篇博文相对独立&#xff0c;所以这里笔者还是先给出完整代码&#xff0c;哪怕跟&#xff08;3&#xff09;没有太大区别。 这里我们把线的粗细调成5&#xff08;排除难选中的因素&#xff09;&#xff…

信息收集 CTF 1 挑战通关指南

大家好&#xff01;今天我想和大家分享 Information Gathering CTF 1 挑战的完整攻略。我将解释我是如何逐步攻克每一个 flag&#xff0c;并使用了哪些工具。放心&#xff0c;我不会直接给出 flag&#xff0c;因为学习的目的不是直接提交答案&#xff0c;而是掌握解决问题的方法…

PHP防伪溯源一体化管理系统小程序

&#x1f50d; 防伪溯源一体化管理系统&#xff0c;品质之光&#xff0c;根源之锁 &#x1f680; 引领防伪技术革命&#xff0c;重塑品牌信任基石 我们自豪地站在防伪技术的前沿&#xff0c;为您呈现基于ThinkPHP和Uniapp精心锻造的多平台&#xff08;微信小程序、H5网页&…

使用MQTT.fx向阿里云物理网平台上报物理模型数据

MQTT向阿里云物理网平台上报物理模型数据 一、前言二、测试三、结束语 一、前言 上一篇文章介绍了阿里云物联网平台的基本使用&#xff08;文章入口&#xff09;&#xff0c;本篇博客接着来讲&#xff0c;主要介绍如何使用MQTT连接测试工具向阿里云物联网平台上报物理模型数据。…

【阅读笔记】基于图像灰度梯度最大值累加的清晰度评价算子

本文介绍的是一种新的清晰度评价算子&#xff0c;基于图像灰度梯度最大值累加 一、概述 目前在数字图像清晰度评价函数中常用的评价函数包括三类&#xff1a;灰度梯度评价函数、频域函数和统计学函数&#xff0c;其中灰度梯度评价函数具有计算简单&#xff0c;评价效果好等优…

数据库底层存储的基本逻辑

1. 数据库、表空间、磁盘是多对多的关系 一个表空间可以分散到多个磁盘上&#xff0c;一个磁盘上也可以有多个表空间&#xff1b; 一个数据库可以分散存储在多个磁盘上&#xff0c;一个磁盘也可以包含多个数据库。 2. 一个表只能属于一个库&#xff0c;也只能对应一个表空间…

80,【4】BUUCTF WEB [SUCTF 2018]MultiSQL

53&#xff0c;【3】BUUCTF WEB october 2019 Twice SQLinjection-CSDN博客 上面这个链接是我第一次接触二次注入 这道题也涉及了 对二次注入不熟悉的可以看看 BUUCTF出了点问题&#xff0c;打不开&#xff0c;以下面这两篇wp作为学习对象 [SUCTF 2018]MultiSQL-CSDN博客 …

FFmpeg 头文件完美翻译之 libavcodec 模块

前言 众所周知&#xff0c;FFmpeg 的代码开发上手难度较高&#xff0c;源于官方提供的文档很少有包含代码教程相关的。要想熟练掌握 FFmpeg 的代码库开发&#xff0c;需要借助它的头文件&#xff0c;FFmpeg 把很多代码库教程都写在头文件里面。因此&#xff0c;熟读头文件的内…

redis实现lamp架构缓存

redis服务器环境下mysql实现lamp架构缓存 ip角色环境192.168.242.49缓存服务器Redis2.2.7192.168.242.50mysql服务器mysql192.168.242.51web端php ***默认已安装好redis&#xff0c;mysql 三台服务器时间同步&#xff08;非常重要&#xff09; # 下载ntpdate yum -y install…

PaddleSeg 从配置文件和模型 URL 自动化运行预测任务

git clone https://github.com/PaddlePaddle/PaddleSeg.git# 在ipynb里面运行 cd PaddleSegimport sys sys.path.append(/home/aistudio/work/PaddleSeg)import os# 配置文件夹路径 folder_path "/home/aistudio/work/PaddleSeg/configs"# 遍历文件夹&#xff0c;寻…

ESMC-600M蛋白质语言模型本地部署攻略

前言 之前介绍了ESMC-6B模型的网络接口调用方法&#xff0c;但申请token比较慢&#xff0c;有网友问能不能出一个本地部署ESMC小模型的攻略&#xff0c;遂有本文。 其实本地部署并不复杂&#xff0c;官方github上面也比较清楚了。 操作过程 环境配置&#xff1a;CUDA 12.1、…

HTML<hgroup>标签

例子&#xff1a; 使用hgroup元素标记标题和段落是相关的&#xff1a; <hgroup> <h2>Norway</h2> <p>The land with the midnight sun.</p> </hgroup> 定义和用法&#xff1a; 标签<hgroup>用于包围标题和一个或多个<p&g…