web登录校验

news2024/12/23 13:19:34

基础登录功能

在这里插入图片描述
LoginController

@PostMapping("/login")
    Result login(@RequestBody Emp emp) {
        log.info("前端,发送了一个登录请求");
        Emp e = empService.login(emp);

        return e!=null?Result.success():Result.error("用户" +
                "名或密码错误");
    }

Service

@Override
    public Emp login(Emp emp) {
        return empMapper.login(emp);
    }

DAO

   @Select("SELECT * From emp WHERE username=#{username} and" +
           "password=#{password}")
   Emp login(Emp emp);

利用Postman进行校验
在这里插入图片描述
乱输得用户名和密码.

退出后,访问相应地页面的url,直接进入了系统的页面.这时候用户名和密码就变得没有意义.

这时候就需要进行登录校验

登录校验

在这里插入图片描述

会话技术

在这里插入图片描述
令牌技术是当前企业开发中最主流的技术

会话跟踪

在这里插入图片描述

在请求时,后端自动给访问的浏览器生成了一个cookie并通过响应头{set-cookie}返回给浏览器。此后浏览器每次发送请求都会向浏览器自动发送这个cookie(cookie请求头)

Cookie
//设置cookie
    @GetMapping("/c1")
    public Result cookie(HttpServletResponse response) {

        // Cookie参数也是一个键值对
        response.addCookie(new Cookie("logusername","jzr10086"));

        return Result.success();
    }

发送请求 http://localhost:8080/c1
在这里插入图片描述
响应头中set-cookie头被设置为指定的参数

获取Cookie
//获取cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request) {

        Cookie[] cookies = request.getCookies();
        for(Cookie cookie : cookies) {
            if(cookie.getName().equals("logusername")) {
                System.out.println(cookie.getName()+cookie.getValue());
            }
        }

        return Result.success();
    }

在这里插入图片描述

访问c2时携带了对应的cookie,这样就建立了一次会话,当服务器停止运行或者浏览器关闭才会结束会话。
在这里插入图片描述

跨域:

在这里插入图片描述
这时候如果服务器端要设置cookie将无法使用。因为服务器端无法跨域访问到前端。

Session

设置Session
//设置session
    @GetMapping("/s1")
    public Result session(HttpSession session) {
        log.info("Http-session-s1:{}" , session.hashCode());

        session.setAttribute("logusername","jzr10086");
        return Result.success();
    }

访问 localhost:8080/s1
在这里插入图片描述
Set-Cookie是Session对象的id;

cookie储存在本地浏览器上
session储存在服务器上

获取Session
//获取session
    @GetMapping("/s2")
    public Result session2(HttpSession session) {
        log.info("Http-session-s2:{}" , session.hashCode());

        Object obj = session.getAttribute("logusername");
        log.info("session2:{}" , obj.toString());
        return Result.success();
    }

访问s2:
在这里插入图片描述
两次请求的hashcode相同,说明两次请求共用了一个session
在这里插入图片描述

同一个浏览器发送的请求可能被负载均衡服务器转到不同的后端服务器上,导致后端服务器找不到对应的session对象
在这里插入图片描述
在这里插入图片描述

JWT令牌

在这里插入图片描述
缺点:需要自己实现令牌的生成检验等操作

服务端在浏览器请求之后,生成一个令牌并传送给浏览器。此后每次请求都会有服务端校验令牌的有效性。

在这里插入图片描述
在这里插入图片描述

生成校验JWT

依赖:
在这里插入图片描述

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

在这里插入图片描述

@Test
    void testGenJwt() {
        claims.put("id","1");
        claims.put("name","test");

        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256,"jzr666") //生成JWT令牌使用的算法和密钥
                .setClaims(claims) //自定义内容(载荷)
                .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)) //设置有效期
                .compact(); //按照要求生成对应的数字令牌

        System.out.println(jwt);

    }

在这里插入图片描述
运行单元测试类,生成了对应的令牌。
可以通过公钥解密之后看到对应的JWT令牌内容,但是内容不可被更改。对应得JWT令牌不可被伪造。
·
利用对应的密钥进行解码

 @Test
    void praseJwt(){
        Claims claim = Jwts.parser()
                        .setSigningKey("jzr666") //指定签名密钥
                        .parseClaimsJwt("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidGVzdCIsImlkIjoiMSIsImV4cCI6MTcyNTY4Mjk1NH0.O3q9xHqoMJAf1Pm1vdmmUzADXsUsBoQLaKa-Vc3bVsQ") //注意是jws不是jwt
                        .getBody();

        System.out.println(claim);
    }

获取到了载荷中存放的内容
在这里插入图片描述
如果篡改令牌中的任意一个字符,在解析的时候都会报错。令牌过期之后,解析也会报错

登陆后下发令牌

在这里插入图片描述
通过Result响应以Json格式返回给前端
在这里插入图片描述
以后前端在每次请求时,都会将令牌携带到服务端(通过请求头的token)。

过滤器Filter

在这里插入图片描述
在这里插入图片描述

快速入门

在这里插入图片描述

实现接口并重写三个方法:
在这里插入图片描述
在启动类中加入ServletComponentScan,因为Filter组件并不属于SpringBoot的内容

package com.yuyu.realproject.Filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

//表示拦截所有请求
@WebFilter("/*")
public class DemoFilter implements Filter {

    @Override//初始化方法,只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Init初始化方法执行了");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter初始化方法执行了");
        //调用doFilter方法放行,继续访问对应的资源
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override //销毁方法,只调用一次
    public void destroy() {
        System.out.println("拦截到了请求");
    }
}

在请求之前的emps查询接口时,首先被doFilter函数拦截,然后执行filterChain的doFilter操作放行,然后开始执行查询操作
在这里插入图片描述
从控制台的日志中可以看到idoFilter函数的执行过程
在这里插入图片描述
记得要再过滤器的Controller类上加上WebFilter注解。

详解
执行流程

1.放行前逻辑
2.放行操作,进行前端请求的操作
3.执行完毕,放行后逻辑
在这里插入图片描述
在这里插入图片描述

拦截路径

在这里插入图片描述

过滤器链

在这里插入图片描述
在这里插入图片描述

DoFilter实际上是将当前的服务放行到下一个过滤器,如果后面没有过滤器了,则访问对应的web资源

类名在软件包中排名越靠前,越早执行。由于Java类在软件包中按照字符串的顺序进行排序,所以只需要重构类名,就能得到所需要的执行顺序。
在这里插入图片描述
小结:
在这里插入图片描述

登录校验(利用过滤器实现)

在这里插入图片描述
1.执行登录请求时并不需要Jwt令牌
2.Jwt令牌存在且有效就允许放行

过程:
在这里插入图片描述
登录检验过滤器的实现

package com.yuyu.realproject.Filter;

import com.alibaba.fastjson.JSONObject;
import com.yuyu.realproject.Pojo.Result;
import com.yuyu.realproject.utils.JwtUtils;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import java.io.IOException;

@Slf4j
@WebFilter("/*")
public class LoginCheckFilter implements Filter {
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //获取请求和响应对象
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String url = request.getRequestURI().toString();

        if (url.contains("login")) {
            log.info("登录请求,直接放行");
            filterChain.doFilter(request, response);
            return;
        }
        String Jwt = request.getHeader("token");

        if(StringUtils.hasLength(Jwt)){
            log.info("请求头中没有相应地令牌");
            Result error = Result.error("not login in");
            //手动转换json对象,使用阿里的fastjson工具包
            String notlogin = JSONObject.toJSONString(error);
            //直接将登录失败的信息相应给浏览器
            response.getWriter().write(notlogin);
            return;
        }
        try{
            JwtUtils.praseJwt(Jwt);
        }catch (Exception e){
            e.printStackTrace();
            log.info("当前令牌无效");
            Result error = Result.error("not login in");
            //手动转换json对象,使用阿里的fastjson工具包
            String notlogin = JSONObject.toJSONString(error);
            //直接将登录失败的信息相应给浏览器
            response.getWriter().write(notlogin);
            return;
        }

        //如果登录成功,直接放行
        filterChain.doFilter(request,response);
    }
}

e.printStackTrace()是 Java 中的一种异常处理机制中的语句。
以下是关于它的详细解释:
基本含义
在 Java 编程中,当程序运行过程中发生异常(Exception)时,可以通过try - catch语句块来捕获异常。e.printStackTrace()通常放在catch块中,其中e是捕获到的异常对象。它的主要作用是打印异常的堆栈跟踪信息。

前端看到Not_login标识会自动重定向到登录页面。 也就是说这步操作是在前端实现的

拦截器Interceptor

拦截器和Fillter的区别在于是由Spring提供的?
在这里插入图片描述
在这里插入图片描述
1.进行HandlerInterceptor的实现

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    //按ctrl+o进行生成

    //目标资源方法运行前运行,返回true放行,返回false不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println ("preHandler 运行了");

        return true;
    }

    //目标资源方法运行后运行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println ("postHandler 运行了");
    }

    @Override //视图渲染完成后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println ("运行完了");
    }
}

2.进行拦截器的配置,添加拦截器,记得加上configuration注解

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    //添加拦截器的配置
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor (loginInterceptor).addPathPatterns("/**");
    }
}

在这里插入图片描述
从日志中可以看到,拦截器的preHandler首先执行,return true之后,放行进入登录的Controller,执行结束后执行postController。当所有操作结束之后,这个请求由一个afterCompletion进行终结
在这里插入图片描述

拦截路径的配置:
在这里插入图片描述
不同拦截路径的配置
在这里插入图片描述
在这里插入图片描述

过滤器和拦截器的区别

当过滤器和拦截器同时存在时:

登录校验:
和过滤器的逻辑基本类似。

异常处理

在这里插入图片描述
出现异常的时候,返回的异常并不符合开发文档中定义的错误,所以前端无法对这样的异常进行处理。

如果需要新增的部门已经存在,由于部门表中用部门名称作为主键,sql的insert语句会报错,服务器会返回500错误。但是前端不抓包的话并不会发现这样的错误。

在这里插入图片描述

方案:全局异常处理器

在这里插入图片描述
在这里插入图片描述
加上RestControllerAdvice注解,在捕获异常的方法中要加上ExceptionHandler注解
在这里插入图片描述
这样所有的异常都会返回异常的Json数据。
这个注解包含ResponseBody,会将返回的对象转化为Json格式,所以不需要自己手动转换

@RestControllerAdvice
public class exceptionHandler {

    @ExceptionHandler(Exception.class)
    public Result ex(Exception e){
        e.printStackTrace ();
        return Result.error ("服务访问失败,请练习管理员");
    }

}

这样就把异常转化成了前端可以处理的Result
在这里插入图片描述

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

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

相关文章

isxdigit函数讲解 <ctype.h>头文件函数

目录 1.头文件 2.isxdigit函数使用 方源一把抓住VS2022&#xff0c;顷刻 炼化&#xff01; ​​​​​​​ 1.头文件 以上函数都需要包括头文件<ctype.h> &#xff0c;其中包括 isxdigit 函数 #include<ctype.h> 2.isxdigit函数使用 isxdigit 函数是判断字符…

Leetcode Hot 100刷题记录 -Day10(合并区间)

合并区间 问题描述&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti,endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&…

vscode从本地安装插件

1. 打开VSCode。 2. 点击左侧菜单中的“扩展”&#xff08;或按CtrlShiftX&#xff09;。 3. 点击“更多操作”&#xff08;三个点&#xff09;> “从VSIX安装”。 4. 选择下载的.vsix文件。 5. 点击“安装”即可安装插件。

IstoreOS安装的1Panel无法安装应用

IstoreOS安装的1Panel无法安装应用&#xff0c;无法安装OpenResty&#xff0c;创建Docker提示文件不存在 这个路径&#xff1a; /root/Configs/1Panel/1panel/apps/openresty/openresty/www /root/Configs/1Panel/1panel/apps/openresty/openresty/1pwaf/data /root/Configs/…

请求响应-02.请求-postman工具

一.前后端分离开发 当前主流的开发模式是前后端分离开发&#xff0c;每开发一个功能&#xff0c;就需要对该功能接口进行测试&#xff0c;当前我们的测试方法是直接将url地址输入到浏览器中&#xff0c;查看web页面是否满足我们的要求。但是浏览器发起的请求全部都是GET请求&am…

【笔记】408刷题笔记

文章目录 三对角三叉树求最小带权路径UDP报文首部和TCP报文首部IP报文首部TCP报文首部UDP报文首部 刷新和再生的区别地址译码 为了区分队空队满&#xff0c;可以使用三种处理方式 1&#xff09;牺牲一个单元 队头指针在队尾指针的下一位置作为队满的标志 队满条件&#xff1a;(…

每日一题,力扣leetcode Hot100之238.除自身以外数组的乘积

乍一看这个题很简单&#xff0c;但是不能用除法&#xff0c;并且在O(N)时间复杂度完成或许有点难度。 考虑到不能用除法&#xff0c;如果我们要计算输出结果位置i的值&#xff0c;我们就要获取这个位置左边的乘积和右边的乘积&#xff0c;那么我新设立两个数组L和R。 对于L来…

Hive 本地启动时报错 Persistence Manager has been closed

Hive 本地启动时报错 Persistence Manager has been closed 2024-09-07 17:21:45 ERROR RetryingHMSHandler:215 - Retrying HMSHandler after 2000 ms (attempt 2 of 10) with error: javax.jdo.JDOFatalUserException: Persistence Manager has been closedat org.datanucle…

使用亚马逊Bedrock的Stable Diffusion XL模型实现文本到图像生成:探索AI的无限创意

引言 什么是Amazon Bedrock&#xff1f; Amazon Bedrock是亚马逊云服务&#xff08;AWS&#xff09;推出的一项旗舰服务&#xff0c;旨在推动生成式人工智能&#xff08;AI&#xff09;在各行业的广泛应用。它的核心功能是提供由顶尖AI公司&#xff08;如AI21 Labs、Anthropic…

基于 RocketMQ 的云原生 MQTT 消息引擎设计

作者&#xff1a;沁君 概述 随着智能家居、工业互联网和车联网的迅猛发展&#xff0c;面向 IoT&#xff08;物联网&#xff09;设备类的消息通讯需求正在经历前所未有的增长。在这样的背景下&#xff0c;高效和可靠的消息传输标准成为了枢纽。MQTT 协议作为新一代物联网场景中…

Windows 11安装nvm教程

1、nvm是什么 nvm 全名 node.js version management&#xff0c;是一个 nodejs 的版本管理工具。通过它可以安装和切换不同版本的 nodejs&#xff0c;主要解决 node 各种版本存在不兼容现象。   在工作中&#xff0c;我们可能同时在进行2个或者多个不同的项目开发&#xff0…

一、Maven工程的GAVP属性及项目结构说明

1、GAVP Maven 中的 GAVP 是指 GroupId、ArtifactId、Version、Packaging 等四个属性的缩写&#xff0c;其中前三个是必要的&#xff0c;而 Packaging 属性为可选项。这四个属性主要为每个项目在maven仓库总做一个标识&#xff0c;类似人的《姓-名》。有了具体标识&#xff0c…

高清4K短视频素材网站有哪些?推荐8个高清4K短视频素材网站

是不是还在为找不到合适的4K高清素材而苦恼&#xff1f;别急&#xff01;今天我为大家精心挑选了8个超级优秀的4K高清短视频素材网站&#xff0c;不仅能让你的视频质量爆表&#xff0c;还能大大提高账号的互动率和曝光度&#xff01;每一个推荐都是精心筛选过的&#xff0c;每一…

【leetcode详解】爬楼梯:DP入门典例(附DP通用思路 同类进阶练习)

实战总结&#xff1a; vector常用方法&#xff1a; 创建一个长为n的vector&#xff0c;并将所有元素初始化为某一定值x vector<int> vec(len, x) 代码执行过程中将所有元素更新为某一值x fill(vec.begin(), vec.end(), x) // 更多实战方法欢迎参考文章&#xff1a;…

SpringBoot教程(十五) | SpringBoot集成RabbitMq(消息丢失、消息重复、消息顺序、消息顺序)

SpringBoot教程&#xff08;十五&#xff09; | SpringBoot集成RabbitMq&#xff08;消息丢失、消息重复、消息顺序、消息顺序&#xff09; RabbitMQ常见问题解决方案问题一&#xff1a;消息丢失的解决方案&#xff08;1&#xff09;生成者丢失消息丢失的情景解决方案1&#xf…

TensorRT-LLM高级用法

--multi_block_mode decoding phase, 推理1个新token&#xff0c; 平时&#xff1a;按照batch样本&#xff0c;按照head&#xff0c;将计算平均分给所有SM&#xff1b; batch_size*num_heads和SM数目相比较小时&#xff1a;有些SM会空闲&#xff1b;加了--multi_block_mode&…

JavaScript 知识点(从基础到进阶)

&#x1f30f;个人博客主页&#xff1a;心.c ​ 前言&#xff1a;JavaScript已经学完了&#xff0c;和大家分享一下我的笔记&#xff0c;希望大家可以有所收获&#xff0c;花不多说&#xff0c;开干&#xff01;&#xff01;&#xff01; &#x1f525;&#x1f525;&#x1f5…

urllib与requests爬虫简介

urllib与requests爬虫简介 – 潘登同学的爬虫笔记 文章目录 urllib与requests爬虫简介 -- 潘登同学的爬虫笔记第一个爬虫程序 urllib的基本使用Request对象的使用urllib发送get请求实战-喜马拉雅网站 urllib发送post请求 动态页面获取数据请求 SSL证书验证伪装自己的爬虫-请求头…

【redis】数据量庞大时的应对策略

文章目录 为什么数据量多了主机会崩分布式系统应用数据分离架构应用服务集群架构负载均衡器数据库读写分离 引入缓存冷热分离架构 分库分表微服务是什么代价优势 为什么数据量多了主机会崩 一台主机的硬件资源是有上限的&#xff0c;包括但不限于一下几种&#xff1a; CPU内存…

【最新华为OD机试E卷-支持在线评测】猜字迷(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,…