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

登录认证

需求:输入登录请求服务器判断用户的用户名和密码
//控制层
@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());
    }
}

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

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

相关文章

旋转矩阵(将坐标轴旋转)

旋转矩阵&#xff08;将坐标轴旋转&#xff09; 在二维空间中&#xff0c;旋转可以用一个单一的角 定义。作为约定&#xff0c;正角表示逆时针旋转。把笛卡尔坐标的列向量关于原点逆时针旋转的矩阵是&#xff1a; 原坐标系下 坐标系逆时针旋转β 补充 sin(-a) -sin(a) co…

RuntimeError: Tensor must have a last dimension with stride 1

我在使用torch.view_as_complex将weight转化为复数时&#xff0c;遇到了这样一个错误&#xff1a;由于我在对weight使用view_as_complex之前使用了F.interpolate函数进行了分辨率调整&#xff0c;因此只需对张量weight添加.contiguous()即可。

【操作系统】进程与线程概念基础知识

进程与线程概念基础知识 进程进程的概念进程控制块进程状态进程三状态模型挂起进程模模型进程的上下文切换进程控制 线程为什么引入线程线程的概念线程与进程的比较线程的上下文切换线程的实现 进程 进程的概念 1. 进程的定义&#xff1a; 进程是指一个具有一定独立功能的程序…

QT 客户端软件开发

QT 是一种功能强大且灵活的跨平台应用程序开发框架&#xff0c;但也存在一些技术难点&#xff0c;需要开发者仔细考虑和克服。以下是一些常见的 QT 软件开发的技术难点。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 跨平台兼容性…

C# 和 Qt 相比的一些优势

C# 和 Qt 都是流行的软件开发工具&#xff0c;它们各自具有不同的优势&#xff0c;适用于不同的开发场景。以下是 C# 和 Qt 相比的一些优势。相比之下&#xff0c;Qt 也有其独特的优势&#xff0c;特别是在跨平台 GUI 应用程序开发方面。然而&#xff0c;C# 的这些优势使得它在…

MySQL mydumper工具

目录 1. mydumper介绍 2. mydumper参数解释 3. 备份例子 3.1 备份全库(未包含其他) 3.2 备份全库(包含其他) 3.3 备份指定数据库(-B或--database) 3.4 导出指定表(-T或--tables-list) 3.5 只导出表结构&#xff0c;不导出表数据(-d或--no-data) 3.6 只导出表数据&#…

计算机毕业设计 | springboot+vue凌云在线阅读平台 线上读书系统(附源码)

1&#xff0c;绪论 随着社会和网络技术的发展&#xff0c;网络小说成为人们茶钱饭后的休闲方式&#xff0c;但是现在很多网络小说的网站都是收费的&#xff0c;高额的收费制度是很多人接受不了的&#xff0c;另外就是很多小说网站都会有大量的弹窗和广告&#xff0c;这极大的影…

YOLO组件之C2f模块介绍

C2F类是yolo算法中的组件之一&#xff0c;该类是一个继承自 nn.Module 的神经网络模块。 1. C2f 类的前向传播过程 首先将输入数据经过第一个卷积层 cv1&#xff0c;然后将输出分为两个部分。其中一个部分直接传递给输出&#xff0c;另一个部分经过多个 Bottleneck 模块的处理…

Xinstall助力推广结算统计,让数据一目了然

在当今数字化营销的时代&#xff0c;推广活动的成功与否往往取决于精准的数据统计和分析。然而&#xff0c;对于许多广告主和开发者来说&#xff0c;推广结算统计却是一个令人头疼的问题。数据分散、渠道繁多、统计口径不一&#xff0c;这些问题都给推广效果的衡量带来了极大的…

Unity图文混排EmojiText的使用方式和注意事项

​​​​​​​ 效果演示&#xff1a; 使用方式&#xff1a; 1、导入表情 2、设置图片格式 3、生成表情图集 4、创建/修改目标材质球 5、测试 修复换行问题 修复前&#xff1a; 修复后&#xff1a; 修复代码&#xff1a; 组件扩展 1、右键扩展 2、组件归类&#…

LINUX 入门 4

LINUX 入门 4 day6 7 20240429 20240504 耗时&#xff1a;240min 课程链接地址 第4章 LINUX环境编程——实现线程池 C基础 第3节 #define里面的行不能乱空行&#xff0c;要换行就打\ typedef 是 C 和 C 中的一个关键字&#xff0c;用于为已有的数据类型定义一个新的名字。…

新书速览|图神经网络基础、模型与应用实战

掌握PyTorch图神经网络基础与模型&#xff0c;实战自然语言处理、计算机视觉、推荐系统、社交网络应用开发 01 本书内容 图神经网络不仅能够解决传统机器学习方法无法解决的图数据问题&#xff0c;而且能够应用于许多实际场景&#xff0c;例如社交网络、药物发现、网络安全、…

新手向的s2-046漏洞复现

一、前期准备 1.docker容器 作为第一次接触struts2漏洞类型的小白&#xff0c;第一步从搭建环境开始。首先我们需要准备一个服务器或者本地系统&#xff0c;我这里是使用本地的kali&#xff0c;kali里面需要有docker容器&#xff0c;docker容器的安装教程请自行搜索&#xff0c…

女性名字有孤寡数,易离婚

丁老师&#xff1a;您好&#xff01;我孩子&#xff08;女孩&#xff09;准备取名&#xff1a;周小程&#xff0c;宝宝出生于阳历2016年8月13号16时30分左右&#xff0c;准备给孩子取个名字&#xff0c;在网上查询了哈&#xff0c;这个名字的分数还蛮高的&#xff0c;99分&…

韦东山嵌入式Liunx驱动大全二

文章目录 一、LCD1-1 不同接口的LCD硬件操作原理1-2 LCD驱动程序框架1-3 结合APP分析LCD驱动程序框架1-4 LCD硬件时序图1-5 分析内核自带的LCD驱动程序1-6 编程LCD驱动程序框架_使用设备树1-7 LCD驱动程序框架_引脚配置1-8 LCD驱动程序框架_时钟配置1-9 LCD驱动程序框架_LCD控制…

1069 微博转发抽奖

solution #include<iostream> #include<string> #include<map> using namespace std; int main(){int n, m, s, loop 0, have 0;string id;map<string, int> mp;cin >> m >> n >> s;for(int i 1; i < m; i){//编号从1开始cin…

专题五_位运算(3)

目录 137. 只出现一次的数字 II 解析 题解 面试题 17.19. 消失的两个数字 解析 题解 137. 只出现一次的数字 II 137. 只出现一次的数字 II - 力扣&#xff08;LeetCode&#xff09; 解析 注意这里指的是比特位上的01来进行统计的 题解 class Solution { public:int sin…

Unity与C#的关系

第一&#xff0c;我们首先需要知道Unity与C#的关系是什么&#xff1f; 第二&#xff0c;我们要明白为什么Unity会使用C#&#xff0c;而不是C&#xff1f; 第三&#xff0c;我们需要知道Unity是怎么使用C#的&#xff1f; 第一点&#xff1a; 先说结论&#xff1a;C#是Unity用…

windows如何安装python框架

windows如何安装Python框架&#xff1f;以安装Django框架为例&#xff0c;具体如下&#xff1a; 在idea上运行Python项目时&#xff0c;出现了如下错误&#xff0c;这是因为系统中只安装了Python&#xff0c;没有安装Django。 既然报错的原因就是缺少Django&#xff0c;那我们…

深度解析 Spring 源码:揭秘 AbstractAutowireCapableBeanFactory 的 Bean 生命周期处理

文章目录 一、AbstractAutowireCapableBeanFactory 概述1.1 详细分析1.2 设计思想 二、深入解析AbstractAutowireCapableBeanFactory 的实现细节2.1 Bean 实例化过程分析2.1.1 createBean()2.1.2 createBeanInstance() 2.2 Bean 属性注入的实现机制2.2.1 populateBean()2.2.2 a…