18.JavaWeb-JWT(登录、鉴权)

news2024/11/24 19:05:36

1.CSRF跨站请求伪造

        跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

        为了防止CSRF攻击,产检的防御措施有:生成随即令牌(token)、设置Cookie的SameSite属性为Strict或Lax 、验证Referer字段、双重身份验证等

2.JWT概念

        JWT(JSON Web Token)是一种用于进行身份验证和授权的开放标准(RFC 7519)。它是一种安全的、基于JSON的令牌,用于在客户端和服务器之间传递声明

 2.1 JWT组成

header声明类型、声明加密的算法,通常直接使用HMAC SHA256或RSA
payload也称为JWT Claims,包含用户的一些非隐私数据(秘钥、签发人、签发时间、有效时间等)
Signature签证信息,由三部分组成:header(base64后的)、payload(base64后的)、secred

3.登录详细流程

3.1 单token验证

3.1.1 登录成功,生成token并返回

        1.生成token

String token = JWTUtil.generateToken(user.getId());

        2.设置响应头

response.setHeader("authorization", token);

        3.暴露响应头

        浏览器不认识自定义的头,如果不暴露浏览器会自动屏蔽

response.setHeader("Access-Control-Expose-Headers","authorization");

3.1.2 前端得到token保存在浏览器本地

        sessionstorage:在会话期间有效(浏览器打开期间)
        localstorage:只要不主动删除、不卸载浏览器,数据一直有效

let token = res.headers.authorization
window.localStorage.setItem("authorization", token)

3.1.3 通过axios拦截器自动携带token

http.interceptors.request.use(
  config =>{
    // 得到token  本地
    let token = window.localStorage.getItem("authorization")
    config.headers.authorization = token
    // 放行请求
    return config
  }
)

3.1.4 自定义过滤器验证token

if (token == null || token.length() == 0 || token.equals("null")){
    // 没登录
    extracted(servletResponse);
    // 终止
    return;
}else {
    // 有token
    if (JWTUtil.verify(token) == TokenEnum.TOKEN_SUCCESS){
        // 合法,放行
        request.getSession().setAttribute("uid", JWTUtil.getuid(token));
        filterChain.doFilter(servletRequest, servletResponse);
    }else {
        // 伪造或者过期,都让登录
        extracted(servletResponse);
        // 终止请求
        return;
    }
}

private static void extracted(ServletResponse servletResponse) throws IOException {
    ResponseResult<Object> responseResult = new ResponseResult<>(403,"无法访问此界面,请登录",null);
    //转json
    String json = new ObjectMapper().writeValueAsString(responseResult);
    //设置响应头
    servletResponse.setContentType("application/json;charset=utf-8");
    servletResponse.getWriter().write(json);
}

3.2 双token验证(安全性更高)

3.2.1 登录成功生成两个token

//生成Token令牌
String token = JWTUtil.generateToken(user.getId());
//生成refreshToken
String refreshtoken = UUID.randomUUID().toString();

3.2.2 以refreshtoken作为key,token作为value放入Redis并设置过期时间

redisTemplate.opsForValue().set(refreshtoken,token,JWTUtil.REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);

3.2.3 设置响应头、暴露头

//将token放到响应头中返回给前端(流行做法)
response.setHeader("authorization",token);
response.setHeader("refreshtoken",refreshtoken);
//暴露头,浏览器不认识自定义的头,如果不暴露浏览器会自动屏蔽
response.setHeader("Access-Control-Expose-Headers","authorization,refreshtoken");

3.2.4 前端在响应拦截器上得到两个token放到本地

http.interceptors.response.use(
  response =>{
    // 判断响应中是否有token信息,如果有则将token放到本地
    let token = response.headers.authorization
    if(token){
      // 不为空放本地
      window.localStorage.setItem("authorization", token)
    }
    let refreshtoken = response.headers.refreshtoken
    console.log(refreshtoken)
    if(refreshtoken){
      window.localStorage.setItem("refreshtoken", refreshtoken)
    }
    return response
  }
)

3.2.5 前端在请求拦截将两个token设置到请求头

http.interceptors.request.use(
  config =>{
    // 从浏览器本地得到token
    let token = window.localStorage.getItem("authorization")
    let refreshtoken = window.localStorage.getItem("refreshtoken")
    config.headers.authorization = token
    config.headers.refreshtoken = refreshtoken
    // 放行请求
    return config
  }
)

3.2.6 在AuthFilter校验两个token

//需要登录
//获取token
String token = request.getHeader("authorization");
String refreshtoken = request.getHeader("refreshtoken");

//校验refreshtoken是否过期
if(refreshtoken==null || refreshtoken.length()==0 || refreshtoken.equals("null")||!redisTemplate.hasKey(refreshtoken)){
    //非法、过期   去登陆
    extracted(servletResponse);
    return;
}
//判断token
if(token==null || token.length()==0 || token.equals("null")){
    //没登陆
    extracted(servletResponse);
    return;
}else{
    if(JWTUtil.verify(token) == TokenEnum.TOKEN_SUCCESS){
        //进一步的安全验证
        if(token.equals(redisTemplate.opsForValue().get(refreshtoken))){
            //合法,登录成功
            //过滤器放行:让后面的过滤器 或者 servlet处理这个请求
//                    request.getSession().setAttribute("uid",JWTUtil.getuid("authorization"));
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
            //伪造
            extracted(servletResponse);
            return;
        }
    }else if(JWTUtil.verify(token) == TokenEnum.TOKEN_EXPIRE){
        //过期 重新生成token
        token = JWTUtil.generateToken(JWTUtil.getuid(token));
        //判断token与后台记录的是否一致
        //进一步的安全验证
        if(token.equals(redisTemplate.opsForValue().get(refreshtoken))){
            //修改redis的数据
            redisTemplate.opsForValue().set(refreshtoken,token,JWTUtil.REFRESH_TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);
            //将新的token返回前端
            //将token放到响应头中返回给前端(流行做法)
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setHeader("authorization",token);
            response.setHeader("refreshtoken",refreshtoken);
            //暴露头,浏览器不认识自定义的头,如果不暴露浏览器会自动屏蔽
            response.setHeader("Access-Control-Expose-Headers","authorization");
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
            //伪造
            extracted(servletResponse);
            return;
        }
    }else{
        //伪造
        extracted(servletResponse);
        return;
    }

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

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

相关文章

SOCKET编程基本原理

测试模拟环境 python 3.8—对应Pycharm 专业版 for linux 本文采用的环境是vmware + ubantu_64 先简单配置一下netstat工具 sudo apt-get install net-tools netstate基本用法 sudo netstat -at | grep 1234 // |管道函数 grep匹配正则表达式移除端口用Kill就可以了 SOCK…

Calendar类中的字段常量有哪些?

一、Calendar类介绍 Calender类是Java中用于处理日期和时间的类之一。它提供了一组方法&#xff0c;可以对日期和时间进行各种操作&#xff0c;如获取当前日期和时间、计算日期间的差值、设置特定日期和时间等。 Calendar类是一个抽象类&#xff0c;不能直接实例化&#xff0…

MySQL基础管理

目录 ​编辑 一、数据库管理 1.1语言分类 1.2、DDL 二、MySQL相关文件 三、MySQL相关命令 3.2.1创建表的流程 1.创建新的数据库 2.查看创建的数据库 3.进入text库中&#xff0c;创建表 4.查看text下的所有表 5.查看表的属性 6.向表中添加数据 7.查看表中的数据 1.3查看…

TinyKv调用流程梳理二

addNode生成peer func (c *client) heartbeatStreamLoop() {defer c.wg.Done()for {select {case <-c.ctx.Done():returndefault:}ctx, cancel : context.WithCancel(c.ctx)c.connMu.RLock()stream, err : c.leaderClient().RegionHeartbeat(ctx)c.connMu.RUnlock()if err !…

golang waitgroup

案例 WaitGroup 可以解决一个 goroutine 等待多个 goroutine 同时结束的场景&#xff0c;这个比较常见的场景就是例如 后端 worker 启动了多个消费者干活&#xff0c;还有爬虫并发爬取数据&#xff0c;多线程下载等等。 我们这里模拟一个 worker 的例子 package mainimport (…

Redis实现skipList(跳表) 代码有详解

Redis实现skipList(跳表) 项目介绍 非关系型数据库redis&#xff0c;以及levedb&#xff0c;rockdb其核心存储引擎的数据结构就是跳表。 本项目就是基于跳表实现的轻量级键值型存储引擎&#xff0c;使用C实现。插入数据、删除数据、查询数据、数据展示、数据落盘、文件加载数…

Java-API简析_java.lang.Runtime类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131714695 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

【GESP】2023年06月图形化四级 -- 按身高排序

按身高排序 【题目描述】 默认小猫角色和白色背景。有两个列表,第一个列表“names”存储名字,第二个列表“heights”存储这组名字对应的身高,这些身高由互不相同的正整数组成。 请按身高由大到小排序,同时能够得到对应名字的列表“names”。 例如: 名字列表:names = …

变压器试验交流耐压

试验目的 交流耐压试验是鉴定电力设备绝缘强度最有效和最直接的方法。 电力设备在运行中&#xff0c; 绝缘长期受着电场、 温度和机械振动的作用会逐渐发生劣化&#xff0c; 其中包括整体劣化和部分劣化&#xff0c;形成缺陷&#xff0c; 例如由于局部地方电场比较集中或者局部…

unity 调用C++ dll 操作升级套娃函数调用

之前一直以为C生成dll&#xff0c;在unity中调用时要把传出去的值设置在主函数中&#xff0c;以参数或反回值的形式。 当然在DLL工程中可以说没有主函数&#xff0c;那个可以运行一个函数&#xff0c;其会调用其他函数从而一直调其他相关函数。 那问题是在层级是二或三------…

Android CoroutineScope Dispatchers.Main主线程delay,kotlin

Android CoroutineScope Dispatchers.Main主线程delay&#xff0c;kotlin import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.view.View import android.view.View.OnClickListener import android.widget.Bu…

【sgWaterfall】Vue实现图文瀑布流布局模式,图片预加载显示占位区域阴影,加载完成后向上浮动动画出现,支持不同浏览器尺寸宽度下自适应显示列数

特性&#xff1a; 自动计算每个图片最佳坐标位置&#xff0c;以达到最新加在图片占据位置尽量让整体更加协调图片预加载显示占位区域阴影加载完成后向上浮动动画出现支持不同浏览器尺寸宽度下自适应显示列数 Vue实现图文瀑布流布局模式&#xff0c;图片预加载显示占位区域阴影&…

SQL语法与数据库快速入门(2)

目录&#xff1a; 多表简介SQL 约束-外键约束多表关系简介多表查询多表查询-内连接查询多表查询-外连接查询子查询简介子查询实战数据库进阶redis 内存数据库mongodb nosql 数据库neo4j 图数据库 1.多表简介 多表及使用场景介绍&#xff1a; 多表顾名思义就是在数据库设计中…

【NacosSync】注册中心同步组件使用教程ZooKeeper迁移到Nacos

目录 介绍系统模块架构获取安装包数据库配置启动服务器控制台添加注册中心集群信息添加同步任务注意事项 介绍 NacosSync是一个支持多种注册中心的同步组件,基于Spring boot开发框架,数据层采用Spring Data JPA,遵循了标准的JPA访问规范,支持多种数据源存储,默认使用Hibernate…

【论文阅读】《Distilling the Knowledge in a Neural Network》

【论文阅读】《Distilling the Knowledge in a Neural Network》 推荐指数&#xff1a; 1. 动机 &#xff08;1&#xff09;虽然一个ensemble的模型可以提升模型的效果&#xff0c;但是在效率方面实在难以接受&#xff0c;尤其是在每个模型都是一个大型的网络模型的时候。 &…

《TCP IP网络编程》第五章

第5章 基于 TCP 的服务端/客户端&#xff08;2&#xff09; 5.1 回声客户端的完美实现 先回顾一下服务器端的 I/O 相关代码&#xff1a; //持续接收客户端发送的数据&#xff0c;并将数据原样发送回客户端&#xff0c;直到客户端关闭连接。 while ((str_len read(clnt_sock,…

CMS垃圾收集器三色标记-JVM(十二)

上篇文章说了CMS垃圾收集器是赋值清除&#xff0c;所以他不可以碎片整理&#xff0c;于是jvm支持两个参数&#xff0c;几次fullGC之后碎片整理压缩空间。Cms他会抢占cpu资源&#xff0c;因为是并行运行&#xff0c;所以会有浮动垃圾。还有执行不确定性&#xff0c;垃圾收集完&a…

Python爬虫学习笔记(三)————urllib

目录 1.使用urllib来获取百度首页的源码 2.下载网页图片视频 3.总结-1 4.请求对象的定制&#xff08;解决第一种反爬&#xff09; 5.编解码 &#xff08;1&#xff09;get请求方式&#xff1a;urllib.parse.quote&#xff08;&#xff09; &#xff08;2&#xff09;get请求…

深度学习——RNN解决回归问题

详细代码与注释 import torch from torch import nn import numpy as np import matplotlib.pyplot as plt# 有利于复现代码 # torch.manual_seed(1) # reproducible# Hyper Parameters TIME_STEP 10 # rnn time step # 输入sin函数的y值&#xff0c;所以输入尺寸为1 INP…

posix ipc之消息队列

note 1.mq_open函数的参数pathname应以/开始&#xff0c;且最多一个/ 2.mq_receive的参数msg_len应大于等于attr.msgsize 3.消息队列写方写时不要求读方就绪&#xff0c;读方读时不要求写方就绪(和管道不同) code #include <fcntl.h> #include <sys/stat.h> #…