SpringBoot:SpringBoot:实战项目TILAS智能学习辅助系统1.3

news2025/1/16 14:00:02

登录认证

需求:输入登录请求服务器判断用户的用户名和密码
//控制层
@PostMapping("/login")
    public Result login(@RequestBody Emp emp);

@Override
    public Result login(Emp emp) {
        Emp emp1 = empService.selectLogin(emp);
        if(emp1 == null){
            System.out.println("用户名或密码错误");
            return Result.error("登录失败");
        }else{
            System.out.println("登录成功");
            Map<String,Object> map = new HashMap<>();
            map.put(emp1.getUsername(),emp1.getPassword());
            String secret = JWTUtils.generateJwt(map);
            return Result.success(secret);
        }
    }

//业务层
Emp selectLogin(Emp emp);

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

//持久层
@Select("select * from emp where username = #{username} and password = #{password}")
    Emp selectLogin(Emp emp);

过滤:

如果没有过滤,用户可以直接通过链接直接访问功能,绕过登录.

所以我们需要

将登录成功的信息进行保存和封装记录成为登录成功的标记.

进行判断和拦截

使用

Filter过滤器和Interceptor拦截器

但是因为HTTP是无状态的,不能在多次请求之间共享数据,所以我们需要使用会话跟踪技术解决

会话跟踪技术解决

会话:

用户打开浏览器,访问web服务器的资源,会话建立,直到一方断开连接结束会话.

在一次会话中可以包含多次请求和响应

从浏览器发出请求到服务端,服务端再响应数据给前端,就完成了一次会话的建立

如果建立会话后,浏览器和服务端都没有被关闭,就会持续会话直到一方结束

中途可以一直使用该会话进行请求的发送和响应

会话跟踪:

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

服务器会收到多个请求,多个请求可能来自于多个浏览器

所以浏览器需要进行以下操作

使用会话跟踪来进行识别
识别请求是否来自于同一个浏览器
识别浏览器后在同一个会话中多次请求间共享数据
实现会话跟踪
客户端会话跟踪技术:Cookie
服务端会话跟踪技术:Session

都可以实现会话跟踪,但Cookie存储在浏览器端,而Session是存储在服务端

请求时创建唯一id的session保存在服务端,响应时封装成cookie在响应头中返回给客户端

请添加图片描述


传统会话跟踪的问题(服务器集群,客户端多样化)
服务器集群:

服务器的并发访问量有限,需要通过代理服务器来分配访问给多个服务器(集群中数据无法共享)

问题主要体现在两个方面

服务器集群环境下Session的共享问题
移动端APP端无法使用Cookie

所以我们使用

令牌技术

登录请求时,如果登录成功可以给前端响应一个令牌(一个特殊的字符串,代表每个用户合法的身份凭证)

前端将登录返回的令牌记录下来保存在自己的客户端

在后续的请求中每次请求都会携带该令牌,在之后服务端使用Filter或Interceptor对所有请求进行拦截并校验,获取请求中携带的令牌进行判断,如果合法就放行,如果不合法就返回错误信息并跳转到登录页面.

解决了集群环境下的认证问题,减轻服务器的存储压力
支持PC端,移动端

JWT令牌

JSON Web Token

一个开发的行业标准,定义了一种简介的,自包含的协议格式,用于在通信双方传递JSON对象,传递的信息经过数字签名可以被验证和信任.

分为三个部分

Header(头)

记录令牌类型,签名算法等,使用Base64编码

Payload(有效载荷)

携带用户信息和过期信息,使用Base64编码

Signature(签名)

防止Token被篡改,确保安全性,是一个字符串

使用秘钥加密

校验时的签名秘钥必须与生成令牌时的秘钥一致.
如果JWT令牌解析校验时报错,说明JWT令牌被篡改或失效了,令牌非法.

使用json进行数据传输,通用型广泛,体积小,便于传输

无需在服务器端保存相关信息

jwt载荷部分可以存储业务相关信息(不能是敏感信息)

生成令牌

public class JWTUtils {
    private static String signKey = "cfjg";
//    private static Long expire = 43200000L;
    public static String generateJwt(Map<String,Object> claims){//生成令牌
        String jwt = Jwts.builder().addClaims(claims)
                //添加数据
                .signWith(SignatureAlgorithm.HS256,signKey)
                //设置算法
                .setExpiration(new Date(System.currentTimeMillis() + 1000L*3*60))
                //设置过期时间
                .compact();
                //生成
        return jwt;
    }

    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                //设置秘钥
                .parseClaimsJws(jwt)
                //解析令牌
                .getBody();
                //获取数据
        return claims;
    }
}

过滤器Filter

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

底层使用动态代理,对请求进行拦截和处理

对token进行判断和解析,如果失败就跳转回login,如果成功就正常访问

public class Filter implements javax.servlet.Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //请求对象,响应对象,拦截对象
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse)servletResponse;
        String url = httpServletRequest.getRequestURI();
        System.out.println(url);
        if(url.matches(".?login.?")){
            System.out.println("login:登录页面");
            filterChain.doFilter(httpServletRequest,httpServletResponse);
            return;
        }else{
            String token = httpServletRequest.getHeader("token");
            if(token == null || token.equals("")){
                httpServletResponse.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN")));
                System.out.println("令牌错误");
                return;
            }
            try{
                JWTUtils.parseJWT(token);
                System.out.println("令牌正确");
                filterChain.doFilter(httpServletRequest,httpServletResponse);
                return;
            }catch (Exception e){
//                filterChain.doFilter(httpServletRequest,httpServletResponse);
                httpServletResponse.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN")));
                System.out.println("令牌错误");
                return;
            }
        }
    }
}

Interceptor拦截器

注册拦截器
@Configuration
public class InterceptorRegist implements WebMvcConfigurer {//注册拦截器
    @Autowired
    LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    }
}
使用拦截器
package com.example.tlias.Interceptor;


import com.alibaba.fastjson.JSONObject;
import com.example.tlias.pojo.Result;
import com.example.tlias.util.JWTUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {//过滤前
        String url = httpServletRequest.getRequestURI();
        System.out.println(url);
        if(url.matches(".?login.?")){
            System.out.println("interceptor running");
            return true;//放行
        }else{
            String token = httpServletRequest.getHeader("token");
            if(token == null || token.equals("")){
                httpServletResponse.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN")));
                System.out.println("interceptor running");
                return false;//拦截
            }
            try{
                JWTUtils.parseJWT(token);
                System.out.println("interceptor running");
                return true;
            }catch (Exception e){
//                filterChain.doFilter(httpServletRequest,httpServletResponse);
                httpServletResponse.getWriter().write(JSONObject.toJSONString(Result.error("NOT_LOGIN")));
                System.out.println("interceptor running");
                return false;
            }
        }
    }

    @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("请求结束");
    }
}

Filter和Interceptor的区别

接口规范的不同:过滤器要实现Filter接口,拦截器需要实现HandlerInterceptor接口

拦截范围不同:过滤器Filter会拦截所有资源,但Interceptor只会拦截Spring环境中的资源

请添加图片描述

异常处理

在SpringBoot项目中的异常如果从控制层向上抛出会暴露给用户,这是不被允许的.

处理异常的方案

1,在Controller中使用trycatch进行处理(过于冗长)

2,全局异常处理器(推荐)

由SpringMVC提供,接收所有Controller中产生的异常,一般在exception包下定义

@RestControllerAdvice//相当于@ResponseBody+@ControllerAdvice
public class GlobalExceptionHandler {//全局异常处理器
    @ExceptionHandler(Exception.class)//接收需要处理的异常的字节码文件
    public Result exceptionHandler(Exception exception){
        return Result.error(exception.getMessage());
    }
}

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

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

相关文章

企业百度百科词条怎么修改

在进行企业百度百科词条的修改前&#xff0c;首先需要做好以下准备&#xff1a; 注册并登录百度账号&#xff1a;只有注册并登录了百度账号&#xff0c;你才能进行词条的编辑和修改。 熟悉百度百科编辑规则&#xff1a;了解百度百科的编辑规则&#xff0c;包括内容要求、格式规…

思通数科大模型在智能数据查询系统中的深度应用:销售数据分析的革新

在企业决策支持系统中&#xff0c;销售数据分析占据着举足轻重的地位。思通数科的大模型技术&#xff0c;结合自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff0c;为智能数据查询系统提供了强大的分析能力。本文将详细描述思通数科大模型在销售数据分析中的应用&am…

2020 年国考【计算机专业】真题及答案

真题及答案 第一部分数学基础课程 一、&#xff08;共 5 分&#xff09;用逻辑符号表达下列语句&#xff08;论域为包含一切事物的合集&#xff09; &#xff08;2 分&#xff09;确诊者并不都有症状&#xff08;注&#xff1a;需给出两种形式表达, 一种用存在量词, 一种用全称…

ASP.NET小型证券术语解释及翻译系统的设计与开发

摘 要 在系统设计上&#xff0c;综合各种翻译类型网站优缺点&#xff0c;设计出具有任何使用者都可添加术语信息的且只有管理员能够实现术语修改及删除等独特方式的术语查看管理系统。此方式能够使术语量快速增大&#xff0c;并且便于使用者及管理员操作&#xff0c;满足相互…

J1019基于SpringBoot的护肤品推荐系统设计与实现(源码+包运行+技术指导)

项目描述 临近学期结束&#xff0c;开始毕业设计制作&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉的困难吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于SpringBoot的护…

万用板是什么?和印刷电路板一样吗?

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

C/C++ 入门(10)list类(STL)

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 欢迎来指教&#xff01; 一、标准库中的list 1、了解 list&#xff1a;是一个双向带头循环链表&#xff0c;不支持随机访问&#xff08;即下标访问&#xff09;&#xff0c;任意位置的插入删除效率高。 …

python与java用途区别有哪些

区别&#xff1a; 1.Python比Java简单&#xff0c;学习成本低&#xff0c;开发效率高。 2.Java运行效率高于Python&#xff0c;尤其是纯Python开发的程序&#xff0c;效率极低。 3.Java相关资料多&#xff0c;尤其是中文资料。 4.Java版本比较稳定&#xff0c;Python2和3不…

《动手学深度学习》预备知识和安装环境

哈喽&#xff0c;欢迎来到自学深度学习小白的文章&#xff0c;本文将介绍anacoda是什么和有什么用&#xff0c;以及在win10环境下如何安装运行环境。 关于anaconda 1.环境 准备开始写代码了&#xff0c;教材总是先叫你配好环境&#xff0c;环境可以堪称一栋房子&#xff0c;…

如何给正弦信号添加12V直流偏置

一个有趣问题的探究&#xff1a; 运放在单电源的情况下只能输出正电压&#xff08;单方向的&#xff09;&#xff0c;这就使得有正负值的信号电压只能输出一半&#xff1a; 【单电源供电的运放如何增加直流偏置】&#xff08;电阻分压法&#xff09;&#xff1a; 单电源供电的…

【工具推荐定制开发】一款轻量的批量web请求命令行工具支持全平台:hey,基本安装、配置、使用

背景 在开发 Web 应用的过程中&#xff0c;作为开发人员&#xff0c;为了确认接口的性能能够达到要求&#xff0c;我们往往需要一个接口压测工具&#xff0c;帮助我们快速地对我们所提供的 Web 服务发起批量请求。在接口联调的过程中&#xff0c;我们通常会用 Postman 等图形化…

认识大模型提示词

一、写作助理 &#x1f4a5;最常使用的 prompt&#xff0c;用于优化文本的语法、清晰度和简洁度&#xff0c;提高可读性。 输入&#xff1a;作为一名写作改进助理&#xff0c;你的任务是改进所提供文本的拼写、语法、清晰、简洁和整体可读性&#xff0c;同时分解长句&#xff…

“情况不明,对子先行”攻略

掼蛋作为一种策略性极强的游戏&#xff0c;不仅考验牌技&#xff0c;更考验玩家的智慧和策略布局。这里主要介绍一下当牌力不足的时候的普通策略—情况不明&#xff0c;对子先行。 当你的牌力不强&#xff0c;或者牌局情况不明朗时&#xff0c;自己手上有有比较多的对子&#x…

爱丁堡大学出新招,大小语言模型配合节约成本!

在大语言模型的应用中&#xff0c;往往面临着成本和性能权衡的问题。 一方面&#xff0c;大型LLM的参数量极大&#xff08;如70B&#xff09;&#xff0c;每次调用都可能带来更多的成本&#xff0c;而小型LLM&#xff08;如7B&#xff09;的成本则更容易被接受。 另一方面&am…

【软件测试】用例篇 -- 详解

一、测试用例的基本要素 测试用例&#xff08;Test Case&#xff09;是为了实施测试而向被测试的系统提供的一组集合&#xff0c;这组集合包含&#xff1a;测试环境、操作步骤、测试数据、预期结果等要素。&#xff08;注意&#xff1a;不需要执行结果&#xff0c;因为执行结果…

四、Redis五种常用数据类型-List

List是Redis中的列表&#xff0c;按照插入顺序保存数据&#xff0c;插入顺序是什么样的&#xff0c;数据就怎么保存。可以添加一个元素到列表的头部(左边)或者尾部(右边)。一个列表最多可以包含232-1个元素(4294967295&#xff0c;每个列表超过40亿个元素)。是一种双向列表结构…

如何获取中国各省市区的边界

前几个专栏我介绍了获取各流域边界的方法&#xff0c;可参见以下的文章&#xff1a; 格林兰岛和南极洲的流域边界文件下载-CSDN博客 读取shp文件中的经纬度坐标-CSDN博客 读取谷歌地球的kml文件中的经纬度坐标_谷歌地球识别穿过矿区的公路,并获取公路的经纬度坐标-CSDN博客 关于…

图像处理:图像噪声添加

文章目录 前言一、高斯噪声二、椒盐噪声三、泊松噪声四、斑点噪声五、指数噪声六、均匀噪声总结 前言 本文主要介绍几种添加图像噪声的方法&#xff0c;用于数据增强等操作。 以下图为例。 一、高斯噪声 高斯噪声就是给图片添加一个服从高斯分布的噪声&#xff0c;可以通过调…

OpenGL 入门(三)—— OpenGL 与 OpenCV 共同打造大眼滤镜

从本篇开始&#xff0c;会在上一篇搭建的滤镜框架的基础上&#xff0c;介绍具体的滤镜效果该如何制作。本篇会先介绍大眼滤镜&#xff0c;先来看一下效果&#xff0c;原图如下&#xff1a; 使用手机后置摄像头对眼部放大后的效果&#xff1a; 制作大眼滤镜所需的主要知识点&…

Qt应用开发(拓展篇)——图表 QChart

一、前言 QChart是一个图形库模块&#xff0c;它可以实现不同类型的序列和其他图表相关对象(如图例和轴)的图形表示。要在布局中简单地显示图表&#xff0c;可以使用QChartView来代替QChart。此外&#xff0c;线条、样条、面积和散点序列可以通过使用QPolarChart类表示为极坐标…