Java阶段四Day09

news2024/11/16 6:35:28

Java阶段四Day09

文章目录

  • Java阶段四Day09
    • 过滤器
      • 创建过滤器
      • 过滤器的作用
      • 执行过滤器
    • 为什么写配置文件
    • 关于登录和认证的区别
    • 前端获取用户状态

过滤器

使用JWT取代Session,不管做什么都携带着JWT,那么服务端不管处理什么请求、或绝大多数请求都要尝试获取JWT进行解析从而识别身份,也就引出了使用过滤器组件来实现不管发什么请求都会获取并识别JWT,过滤器是整个服务器里面最早接收到请求的组件。过滤器可以对请求阻止或者放行。

在这里插入图片描述

在一个服务器端程序中,可以有好多个过滤器,多个过滤器形成链,称为过滤器链。放在链里面,才有意义。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HjTaltFN-1687828167804)(../../../AppData/Roaming/Typora/typora-user-images/image-20230626091701664.png)]

//之前配置的  http.cors();
//允许跨域访问,本质上是启用了Security框架自带的CorsFilter
http.cors();

//在SecurityConfig上添加注解 @EnableWebSecurity(debug = true)  
@EnableWebSecurity(debug = true)    //开启调试模式,在控制台显示很多日志,在生产过程中不宜使用

创建过滤器

@Component
@Slf4j
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    public JwtAuthorizationFilter() {
        log.debug("【持久化Terminal信息进行关联】开始");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws ServletException, IOException {
        log.debug("处理JWT的过滤开始处理当前请求....");
         //过滤器继续执行  即:放行,由下一个过滤器处理
        chain.doFilter(req, resp);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xh7IstjX-1687828167804)(../../../AppData/Roaming/Typora/typora-user-images/image-20230627083807444.png)]

SecurityContextHolderAwareRequestFilter是处理Security上下文的过滤器,当前截图未添加自定义的JWT过滤器,如果将过滤器放在其之后,则无意义,因为先读上下文时还未读到认证信息,所有应该先去解析JWT得到数据,放在Security上下文,再去检查Security上下文,才可以判断用户登录状态,认证信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X4HR3VjH-1687828167805)(../../../AppData/Roaming/Typora/typora-user-images/image-20230627083935376.png)]

@Autowired
private JwtAuthorizationFilter jwtAuthorizationFilter;

@Override
protected void configure(HttpSecurity http) throws Exception {
    //配置Security框架不适应Session

    //SessionCreationPolicy.STATELESS  无状态,无论是否存在Session,都不使用
    //SessionCreationPolicy.NEVER   从不主动创建Session,但是,Session存在的话,会自动使用
   http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);


    // 将自定义的解析JWT的过滤器添加到Security框架的过滤器链中
    // 必须添加在检查SecurityContext的Authentication之前,具体位置并不严格要求
    http.addFilterBefore(jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jFCTtirw-1687828167806)(../../../AppData/Roaming/Typora/typora-user-images/image-20230627084917474.png)]

到这里过滤器刚刚准备好,完成了创建过滤器相关事情。

过滤器的作用

处理JWT的过滤器的主要作用:

  • 尝试接收客户端的请求中携带的JWT数据
  • 尝试解析JWT数据
  • 将解析得到的用户数据创建为Authentication对象,并存入到SecurityContext中

执行过滤器

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws ServletException, IOException {
    log.debug("处理JWT的过滤器开始处理当前请求……");
    // 尝试接收客户端的请求中携带的JWT数据
    // 业内惯用的做法是:客户端会将JWT放在请求头中名为Authorization的属性中
    String jwt = req.getHeader("Authorization");
    log.debug("客户端携带的JWT:{}", jwt);

    // 判断JWT的基本有效性(没有必要尝试解析格式明显错误的JWT数据)
    if (!StringUtils.hasText(jwt) || jwt.length() < JWT_MIN_LENGTH) {
        // 对于无效的JWT,应该直接放行
        log.warn("当前请求中,客户端没有携带有效的JWT,将放行");
        chain.doFilter(req, resp);
        return;
    }

    // 尝试解析JWT数据
    log.debug("尝试解析JWT数据……");
    Claims claims = null;
    //捕获可能出现的异常
    resp.setContentType("application/json; charset=utf-8");
    try {
        claims = Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(jwt)
            .getBody();
    } catch (ExpiredJwtException e) {   //过期异常
        log.warn("解析JWT时出现异常:ExpiredJwtException");
        String message = "操作失败,您的登录信息已经过期,请重新登录!";
        JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_EXPIRED, message);
        PrintWriter writer = resp.getWriter();
        writer.println(JSON.toJSONString(jsonResult));
        writer.close();
        return;
    }catch (MalformedJwtException e) { //格式错误异常
        log.warn("解析JWT时出现异常:MalformedJwtException");
        String message = "非法访问,你的本次操作已经被记录!";
        JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_MALFORMED, message);
        PrintWriter writer = resp.getWriter();
        writer.println(JSON.toJSONString(jsonResult));
        writer.close();
        return;
    } catch (SignatureException e) {    //签名错误异常
        log.warn("解析JWT时出现异常:SignatureException");
        String message = "非法访问,你的本次操作已经被记录!";
        JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_JWT_SIGNATURE, message);
        PrintWriter writer = resp.getWriter();
        writer.println(JSON.toJSONString(jsonResult));
        writer.close();
        return;
    } catch (Throwable e) {
        log.warn("解析JWT时出现异常:{}", e);
        String message = "服务器忙,请稍后再试!【同学们,看到这句时,你应该检查服务器端的控制台,并在JwtAuthorizationFilter中解析JWT时添加处理异常的catch代码块】";
        JsonResult jsonResult = JsonResult.fail(ServiceCode.ERROR_UNKNOWN, message);
        PrintWriter writer = resp.getWriter();
        writer.println(JSON.toJSONString(jsonResult));
        writer.close();
        return;
    }

    //从解析结果中获取用户的信息
    Long id = claims.get("id", Long.class);
    String username = claims.get("username", String.class);
    String authoritiesJsonString = claims.get("authoritiesJsonString", String.class);
    log.debug("JWT中的用户id = {}", id);
    log.debug("JWT中的用户名 = {}", username);
    log.debug("JWT中的用户权限列表 = {}", authoritiesJsonString);

    // 将解析得到的用户数据创建为Authentication对象
    CurrentPrincipal principal = new CurrentPrincipal(); // 当事人
    principal.setId(id);
    principal.setUsername(username);
    Object credentials = null; // 凭证:无需凭证
    List<SimpleGrantedAuthority> authorities
        = JSON.parseArray(authoritiesJsonString, SimpleGrantedAuthority.class);
    Authentication authentication = new UsernamePasswordAuthenticationToken(
        principal, credentials, authorities);

    // 将Authentication对象存入到SecurityContext中
    SecurityContext securityContext = SecurityContextHolder.getContext();
    securityContext.setAuthentication(authentication);

    // 过滤器链继续执行,即:放行
    chain.doFilter(req, resp);
}

为什么写配置文件

写在配置文件里的东西通常可以除程序员之外的人也可以进行修改。且不会被编译,即使项目交付后也可以方便修改,所以一些如过期时间、secretKey都放在配置文件中,而不是单独创建个类

关于登录和认证的区别

  • 登录 输入用户名和密码,只做一次
  • 认证 检查 authentication,每次携带JWT,即每次都执行认证

前端获取用户状态

在登录页面提交表单方法中添加JWT信息,然后在具体用户权限内的方法中添加获取JWT信息

methods: {
    // 提交表单
    submitForm(formName) {
        this.$refs[formName].validate((valid) => {
            if (valid) {
                let url = 'http://localhost:8090/account/users/login';
                console.log('url = ' + url);
                let formData = this.qs.stringify(this.ruleForm);
                console.log('formData = ' + formData);

                this.axios.post(url, formData).then((r) => {
                    let jsonResult = r.data;
                    if (jsonResult.state === 20000) {
                        this.$message({
                            message: '登录成功!',
                            type: 'success'
                        });
                        //添加获取用户JWT信息
                        let loginResult = jsonResult.data
                        localStorage.setItem('localJwt',loginResult.token);
                        localStorage.setItem('currentUserId',loginResult.id);
                        localStorage.setItem('currentUserName',loginResult.username);
                        localStorage.setItem('currentUserAvatar',loginResult.avatar);
                        this.$router.push('/');
                    } else if (jsonResult.state === 40100) {
                        this.$message.error(jsonResult.message);
                    } else {
                        let title = '操作失败';
                        this.$alert(jsonResult.message, title, {
                            confirmButtonText: '确定',
                            callback: action => {
                            }
                        });
                    }
                });
            }
        });
    },
        ...
}
// 执行修改
handleEdit() {
    let url = 'http://localhost:8090/content/tags/' + this.editForm.id + '/update/info';
    console.log('url = ' + url);
    let formData = this.qs.stringify(this.editForm);
    console.log('formData = ' + formData);
	//使用create 获取JWT信息
    this.axios.create({'headers': {'Authorization': localStorage.getItem('localJwt')}}).post(url, formData).then((response) => {
        let jsonResult = response.data;
        if (jsonResult.state === 20000) {
            this.$message({
                message: '修改标签成功!',
                type: 'success'
            });
            this.editFormVisible = false;
            this.loadTagList();
        } else if (jsonResult.state === 40400) {
            let title = '操作失败';
            this.$alert(jsonResult.message, title, {
                confirmButtonText: '确定',
                callback: action => {
                    this.editFormVisible = false;
                    this.loadTagList();
                }
            });
        } else {
            let title = '操作失败';
            this.$alert(jsonResult.message, title, {
                confirmButtonText: '确定',
                callback: action => {
                }
            });
        }
    });
},

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

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

相关文章

如何让金鸣识别转出来的excel表名不为域名?

我们知道&#xff0c;金鸣表格文字识别系统&#xff08;简称金鸣识别&#xff09;可以将图片转为excel表格&#xff0c;使用起来非常方便&#xff0c;由于它采用了超前AI的技术&#xff0c;且经过深度学习&#xff0c;所以它的识别准确率也非常高&#xff0c;让我们节省了不少人…

基于html+css的图展示137

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

jenkins 自动安装nodejs16.16.0版本报错处理

jenkins 自动安装nodejs16.16.0版本报错了&#xff0c;好像访问不了下面的网址&#xff0c;所以下载不了文件报错 那就人工安装吧&#xff0c;下载16.16.0nodejs版本后&#xff0c;到 在这个目录下安装/root/.jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation …

火车售票管理系统

1、项目概要 2 2、数据库设计 2 2.1 数据表 2 2.2 业务表及其字段 4 3、设计与实现 16 3.1业务功能1名称&#xff1a;系统管理 16 3.1-1 员工管理 16 3.1-2 角色维护 18 3.1-2 操作员管理 19 3.2业务功能2名称&#xff1a;列车管理 21 3.2-1 车辆管理 21 3.2-2 站点管理 23 3.2…

021:vue中watch监听页面变化 动态设置iframe元素的高度

第021个 查看专栏目录: VUE — element UI vue项目中如何动态的设置iframe的高度的呢&#xff0c;这里主要用到了监听的功能&#xff0c;页面高度变化时&#xff0c;设定的动态高度也会相应的改变。 template中&#xff1a; <iframe width"100%" :height"f…

maven使用profile动态配置(IDEA演示)

简介 使用Maven的profile来切换不同环境(开发/测试/发布生产)的配置文件 需求简介 通过把不同环境的配置参数信息,放到不同环境的配置文件里(例如:dev.properties开发环境配置文件).Maven在打包的时候根据选择不同的环境(例如dev:生产环境)调用对应的配置文件(dev.properties)…

FPGA XDMA 中断模式实现 PCIE X8 上位机视频传输 提供工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案图像产生、发送、缓存XDMA简介XDMA中断模式图像读取、输出、显示QT上位机及其源码 5、vivado工程详解6、上板调试验证7、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI Express&#xff09;采…

springboot 国家公务员招聘网站-计算机毕设 附源码80528

springboot 国家公务员招聘网站 目 录 摘要 1 绪论 1.1研究背景与意义 1.2开发现状 1.3系统开发技术的特色 1.4springboot框架介绍 1.5论文结构与章节安排 2 2国家公务员招聘网站系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.3.2数据修改流程 2.…

【(不用Ajax)解决 Layui 插件分页点下一页后又自动跳回前一页的问题】

问题描述: 我们在使用Layui插件进行分页会出现一个常见的问题。就是假如我们不用异步的方法进行分页获取后端的数据时&#xff0c;进行window.location.href进行跳转的进行后端分页。 会遇到: 切换页面的时候&#xff0c;点下一页后又自动跳回前一页的问题 原因:有一个curr属…

论文翻译:2021_Real-Time Denoising and Dereverberation wtih Tiny Recurrent U-Net

论文地址&#xff1a;微型循环U-Net实时降噪和去混响 论文代码&#xff1a; https://github.com/YangangCao/TRUNethttps://github.com/amirpashamobinitehrani/tinyrecurrentunet 引用格式&#xff1a;Choi H S, Park S, Lee J H, et al. Real-Time Denoising and Dereverbera…

将画面上的DOM元素转为SVG并且导出

需求如下&#xff1a; import { elementToSVG } from dom-to-svg; let dom document.querySelector(#pane-${this.currentTabIndex}); const svgDocument elementToSVG(dom); const svgString new XMLSerializer().serializeToString(svgDocument); common.download(this.…

Oracle把单行数据拆分成多行

背景&#xff1a;把接收人[JSRID]拆分为多行&#xff0c;接收人是存在一个字段中&#xff0c;以逗号隔开&#xff0c;每次会议的接收人数量不一 建表语句&#xff1a; CREATE TABLE "HYTZGGZS_HYTZGGXXTJ" ("WF_ORUNID" VARCHAR2(255 BYTE) VISIBLE,&quo…

图像增强之图像锐化(边缘增强)之prewitt算子

note matx (-1,0,1;0,0,0;-1,0,1) maty (-1,-1,-1;0,0,0;1,1,1) code // 图像增强之图像锐化(边缘增强)之prewitt算子 void GetPrewittMat(Mat& prewittMatX, Mat& prewittMatY) {prewittMatX (Mat_<int>(3,3) << -1,0,1,0,0,0,-1,0,1);prewittMatY…

linux系统Nginx服务页面优化

文章目录 一、Nginx服务优化1.隐藏版本号2.日志分割3.设置页面压缩4.配置网页缓存时间5.设置连接超时6.Nginx并发设置优化&#xff08;更改进程数&#xff09;7.修改用户与组8.配置防盗链 总结 一、Nginx服务优化 1.隐藏版本号 隐藏Nginx版本号&#xff0c;以避免泄露Nginx的…

使用QFIL刷机步骤

目录 0.注意 1.确认是否出现端口 2. 使用abd命令开启下载端口 3.选择生成类型 4.配置为UFS 5.选择文件 6.加载文件 7.点击Download下载 0.注意 连接手机与电脑时需要手机是开机状态&#xff0c;否则连接不上 操作过程中不能对手机进行任何操作 若操作中未选择&#xff1a…

Python巧解数字变换问题,有点意思(65)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日主题 如何用Python解决数字变换问题 比如&#xff1a; 对于一对正整数a和b&#xff0c;对a只能进行加1&#xff0c;减1…

chatgpt赋能python:Python计算器编程:从入门到精通

Python计算器编程&#xff1a;从入门到精通 随着计算机技术的不断发展&#xff0c;计算器已经成为了我们日常生活中必不可少的工具。Python是一种简单易学的编程语言&#xff0c;也是一种十分适合编写计算器程序的语言。 为什么选择Python编写计算器程序&#xff1f; Python…

网络安全合规-ISO 27701

ISO 27701是什么&#xff1f; 是ISO 27001和 ISO 27002的扩展内容&#xff0c;对建立、实施、维护和持续改进隐私信息管理系统&#xff08;PIMS&#xff09;的各项要求做出了规定&#xff0c;是首部针对隐私信息管理的国际标准。该标准概述了适用于个人可识别信息控制者和处理者…

Cesium中,在shader里访问顶点法向

在shader中访问顶点法相 前提条件&#xff1a;使用cesium内部的geometry&#xff0c;非自定义的geometry&#xff0c;比如BoxGeometry。 构造Geometry时&#xff0c;需要指定vertexFormat里面包含NORMAL,这样在构造Geometry时&#xff0c;Cesium会自动生成顶点法向。在默认情况…

idea打的包字符集为GBK

1.最近对接一个打印机厂家的机器&#xff0c;他们对与打印数据要求字符集是UTF-8的&#xff0c;做完程序在自己idea上运行是是能够打印的&#xff0c;但是打包后&#xff0c;就不能够打印了。然后问了设备方是否是他们机器的原因&#xff0c;后面他们问了我这报错码&#xff0c…