java后端之登录认证

在这里插入图片描述

  • 基础登录功能:根据提供的用户名和密码判断是否存在于数据库
    LoginController.java
@RestController
@Slf4j
public class LoginController {

    @Autowired
    private 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 {

    @Autowired
    private 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
     */
    @Test
    public 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
     */
    @Test
    public 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 {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
//        Filter.super.init(filterConfig);
        System.out.println("初始化过滤器");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Demo 执行过滤操作...放行前逻辑");
        //放行
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("Demo 执行过滤操作...放行后逻辑");
    }

    @Override
    public 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 {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;//强制类型转换,将ServletRequest转换为其子类HttpServletRequest
        HttpServletResponse 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 {

    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring--Bean的生命周期和循环依赖

Bean的生命周期和循环依赖 Bean 的生命周期了解么?Spring中的循环引用什么是循环引用&#xff1f;三级缓存解决循环依赖总结构造方法出现了循环依赖怎么解决&#xff1f; Bean 的生命周期了解么? 整体上可以简单分为四步&#xff1a;实例化 —> 属性赋值 —> 初始化 —…

【云安全】云原生-Docker(五)容器逃逸之漏洞利用

漏洞利用逃逸 通过漏洞利用实现逃逸&#xff0c;主要分为以下两种方式&#xff1a; 1、操作系统层面的内核漏洞 这是利用宿主机操作系统内核中的安全漏洞&#xff0c;直接突破容器的隔离机制&#xff0c;获得宿主机的权限。 攻击原理&#xff1a;容器本质上是通过 Linux 的…

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

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

基于SpringBoot的软件产品展示销售系统

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

hedfs和hive数据迁移后校验脚本

先谈论校验方法&#xff0c;本人腾讯云大数据工程师。 1、hdfs的校验 这个通常就是distcp校验&#xff0c;hdfs通过distcp迁移到另一个集群&#xff0c;怎么校验你的对不对。 有人会说&#xff0c;默认会有校验CRC校验。我们关闭了&#xff0c;为什么关闭&#xff1f;全量迁…

mysql学习笔记-数据库的设计规范

1、范式简介 在关系型数据库中&#xff0c;关于数据表设计的基本原则、规则就称为范式。 1.1键和相关属性的概念 超键:能唯一标识元组的属性集叫做超键。 候选键:如果超键不包括多余的属性&#xff0c;那么这个超键就是候选键 主键:用户可以从候选键中选择一个作为主键。 外…

高并发问题的多维度解决之道

‍‌​​‌‌​‌​‍‌​​​‌‌​​‍‌​​​‌​‌​‍‌​​‌​​‌​‍‌‌​​‌​‌​‍‌​‌​‌‌​​‍‌​‌​‌​​​‍‌​‌​‌​‌​‍‌​‌‌​​‌​‍‌​‌‌​​​​‍‌‌​​‌‌‌‌‍‌‌​​‌​‌‌‍‌​​​‌‌​​‍‌​​‌‌‌​​‍‌…

Windows Defender添加排除项无权限的解决方法

目录 起因Windows Defender添加排除项无权限通过管理员终端添加排除项管理员身份运行打开PowerShell添加/移除排除项的命令 起因 博主在打软件补丁时&#xff0c;遇到 Windows Defender 一直拦截并删除文件&#xff0c;而在 Windows Defender 中无权限访问排除项。尝试通过管理…

数据结构——堆(C语言)

基本概念&#xff1a; 1、完全二叉树&#xff1a;若二叉树的深度为h&#xff0c;则除第h层外&#xff0c;其他层的结点全部达到最大值&#xff0c;且第h层的所有结点都集中在左子树。 2、满二叉树&#xff1a;满二叉树是一种特殊的的完全二叉树&#xff0c;所有层的结点都是最…

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

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

Vue3 + TS 实现批量拖拽 文件夹和文件 组件封装

一、html 代码&#xff1a; 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性&#xff0c;可根据自己需求&#xff0c;在组件外部做调整 <template><div class"dragUpload"><el-dial…

CF 339A.Helpful Maths(Java实现)

题目分析 输入一串式子&#xff0c;输出从小到大排列的式子 思路分析 如上所说核心思路&#xff0c;但是我要使用笨方法&#xff0c;输入一串式子用split分割开&#xff0c;但是此时需要用到转义字符&#xff0c;即函数内参数不能直接使用“”&#xff0c;而是“\\”。分割开后…

naivecv的设计与实现(3): NV12到RGB的转换

准备 NV12 图像 在 github 搜索关键字 “YUVViewer", 找到样例文件&#xff1a; https://github.com/LiuYinChina/YUVViewer/blob/master/Output/720X576-NV12.yuv 它是二进制文件&#xff0c;没有文件头信息&#xff0c;只有像素内容, 排布方式: 先 Y 平面&#xff0c…

我谈区域偏心率

偏心率的数学定义 禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》P312 区域的拟合椭圆看这里。 Rafael Gonzalez的二阶中心矩的表达不说人话。 我认为半长轴和半短轴不等于特征值&#xff0c;而是特征值的根号。…

ansible自动化运维实战--软件包管理模块、服务模块、文件模块和收集模块setup(4)

文章目录 一、软件包管理模块1.1、功能1.2、常用参数1.3、示例 二、服务模块2.1、功能2.2、服务模块常用参数2.3、示例 三、文件与目录模块3.1、file功能3.2、常用参数3.3、示例 四、收集模块-setup4.1、setup功能4.2、示例 一、软件包管理模块 1.1、功能 Ansible 提供了多种…

Elasticsearch 性能测试工具 Loadgen 之 004——高级用法示例

在性能测试中&#xff0c;能够灵活地模拟不同的应用场景是至关重要的。 Loadgen 提供了多种高级用法&#xff0c;帮助用户更好地评估系统在不同负载下的表现。 本文将介绍如何使用 Loadgen 模拟批量摄取、限制客户端负载以及限制总请求数。 一、模拟批量摄取 在实际应用中&…

将点云转换为 3D 网格:Python 指南

3D 数据的世界往往是一个碎片化的景观。 存在点云&#xff0c;其细节丰富&#xff0c;但缺乏表面信息。 有3D 网格&#xff0c;它明确地定义表面&#xff0c;但创建起来通常很复杂。 将点云转换为网格弥补了这一差距并开启了许多可能性&#xff0c;从真实模拟到 3D 数字环境…

智能电动汽车系列 --- 智能汽车向车载软件转型

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

不解释快上车

聊一聊 最近有小伙伴问我有小红书图片和短视频下载的软件吗&#xff0c;我心想&#xff0c;下载那上面的图片和视频做什么&#xff1f;也许是自己没有这方面的需求&#xff0c;不了解。 不过话又说回来&#xff0c;有些很多下载器可能作者没有持续的维护&#xff0c;所以可能…

FPGA实现任意角度视频旋转(完结)视频任意角度旋转实现

本文主要介绍如何基于FPGA实现视频的任意角度旋转&#xff0c;关于视频180度实时旋转、90/270度视频无裁剪旋转&#xff0c;请见本专栏前面的文章&#xff0c;旋转效果示意图如下&#xff1a; 为了实时对比旋转效果&#xff0c;采用分屏显示进行处理&#xff0c;左边代表旋转…