JWT令牌详细解析

news2024/11/13 15:14:00

JWT令牌

  • 前言
  • 一、JWT是什么?
  • 二、JWT与传统Cookie+Session的对比
  • 三、JWT
    • 1. JWT的功能
    • 2. JWT的结构
    • 3. JWT的使用


前言

主要介绍了SpringBoot集成JWT令牌详细说明,JWT方式校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录,验证token更为简单。


一、JWT是什么?

JWT简称JSON、Web、Token,也就是通过JSON形式作为web与应用中的令牌,用于在各方之间安全地将信息作为JSON对象传输。在数据传输过程中还可以完成数据加密、签名等相关处理。
JSON、Web、Token是一个开放标准,它定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全的传输信息。此信息可以验证和信任,因为它是数字签名的,JWT可以使用秘密或使用RSA或ECDSA的公钥/私钥对进行签名。
官网:http://jwt.io/introduction/

二、JWT与传统Cookie+Session的对比

  1. 在传统的用户登录认证中,因为http是无状态的,所以都是采用session方式。用户登录成功,服务端会保证一个session,当然会给客户端一个sessionId,客户端会把sessionId保存在cookie中,每次请求都会携带这个sessionId。

传统Cookie+ Session认证

在这里插入图片描述

  1. cookie+session这种模式通常是保存在内存中,而且服务从单服务到多服务会面临的session共享问题,随着用户量的增多,开销就会越大。而JWT不是这样的,只需要服务端生成token,客户端保存这个token,每次请求携带这个token,服务端认证解析就可。

  2. JWT方式校验方式更加简单便捷化,无需通过redis缓存,而是直接根据token取出保存的用户信息,以及对token可用性校验,单点登录,验证token更为简单。

JWT 认证
用户进行认证,向服务器发送请求,服务器响应请求并进行认证,认证通过后生成JWT即token,响应给前端;后面的每次请求都携带JWT,服务器拦截请求验证token的有效性,正确的token执行业务逻辑响应数据,错误的token返回错误信息给前端,前端展示相应的的信息。

在这里插入图片描述

三、JWT

1. JWT的功能

JWT主要的功能有授权信息交互两种
授权: 用户的授权,一旦用户登录后获得了token,后续一些需要用户权限的请求就不会拒绝请求。
信息交互: JSON Web Token是在各方之间安全传输信息的好方法。因为可以对JWT进行签名(例如:使用公钥/私钥对),所以可以确保发送方信息,由于签名是使用标头和有效负载计算的,因此可以验证内容是否遭到篡改,保证信息的完整性。

2. JWT的结构

本质是一个字符串,token ====> header.payload.singnature
令牌的组成: 标头(header) 、有效负荷(payload) 、签名(singnature)
JWT通常所示:xxxxxx.yyyyyy.zzzzzz

  • header: 标头通常由两部分组成即令牌的类型(JWT)和使用的算法类型。【通常使用Base64编码组成JWT结构的第一部分】
{
  "alg":"HS256",
  "typ":"JWT"
}
  • payload: 有效负载,存储用户的相关的信息和其他数据的声明。【通常使用Base64编码组成JWT结构的第二部分】
{
  "username":"qiumin",
  "password":"123456"
}
  • singnature: 签名,与前面两个部分生成JWT,该签名不能让其他人知道,是保证token不被串改,保证信息的安全。【通常使用Base64编码组成JWT结构的第二部分】
header+"."+payload+"."+singnature ---> 组成唯一的token

3. JWT的使用

  1. 导入JWT依赖
<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.10.3</version>
</dependency>

  1. 生成token
@Test
    public void contentLoad(){
        HashMap<String,Object> map = new HashMap<>();
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND,180);
        String token = JWT.create()
                .withHeader(map)  //header
                .withClaim("username", "qiumin") //payload
                .withClaim("password", "123456") //payload
                .withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256("!FhSD!#VDZF%#FDBD"));//签名

        System.out.println(token);
    }

  1. 验证解析token
 @Test
    public void Auth(){
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256("!FhSD!#VDZF%#FDBD")).build();
        DecodedJWT verify = verifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQ1NiIsImV4cCI6MTY1NzQzODUxNSwidXNlcm5hbWUiOiJxaXVtaW4ifQ.1TIUuWP1d1-vHc71oTw2pH5LAxtCehiiRnaK3tIZob8");
        System.out.println(verify.getHeader());
        System.out.println("payload: "+verify.getClaim("username").asString());
        System.out.println("payload: "+verify.getClaim("password").asString());
        System.out.println("过期时间: "+verify.getExpiresAt());
    }

  1. 常见的JWT异常,封装成工具类JwtUtils
    SignatureVerificationException: 无效签名。
    TokenExpiredException: token过期。
    AlgorithmMismatchException: token算法不一致。
    InvalidClaimException: 失效payload异常。
package com.qiumin.utils;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Calendar;
import java.util.Map;

/**
 * @author qiumin
 * @classname JWTUtils
 * @Description love code
 * @date 2022-07-10 15:33
 */

public class JwtUtils {

    private static final String SING = "!FhSD!#VhDZF%#FDBD";

    /**
     * 获得Token
     * @param map1 header
     * @param map2 payload
     * */
    public static String getToken(Map<String,Object> map1, Map<String,String> map2){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.SECOND,180); //过期时间

        JWTCreator.Builder builder = JWT.create();
        builder.withHeader(map1); //header

        map2.forEach((k,v)->{builder.withClaim(k,v);}); //payload
        builder.withExpiresAt(instance.getTime()); //过期时间
        String token = builder.sign(Algorithm.HMAC256(SING));//签名
        return token;
    }

    /**
     * 验证token
     * @param token 令牌
     * */
    public static void verify(String token){
        JWTVerifier build = JWT.require(Algorithm.HMAC256(SING)).build();
        build.verify(token);
    }

    /**
     * 获取token中的信息
     * @param token 令牌
     * */
    public static DecodedJWT analysis(String token){
        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }

}

  1. 拦截器配置验证token
    创建拦截器的类,配置WebMvcConfigurer,将自己的自定义拦截器装配到容器中
package com.qiumin.interceptor;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qiumin.utils.JwtUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * JwtInterceptor拦截器类
 *
 * @author qiumin
 * @classname JwtInterceptor
 * @Description love code
 * @date 2022-07-14 13:14
 */

public class JwtInterceptor implements HandlerInterceptor {

    /**
     * 拦截器
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        HashMap<String, Object> map = new HashMap<>();
        JwtUtils jwtUtils = new JwtUtils();
        try {
            jwtUtils.verify(token);
            return true;
        }catch (SignatureVerificationException e){
            e.printStackTrace();
            map.put("msg","无效签名!");
        }catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","token过期!");
        }catch (AlgorithmMismatchException e){
            e.printStackTrace();
            map.put("msg","token算法不一致!");
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg","token无效!");
        }
        map.put("state",false);
        response.setContentType("application/json;charset=UTF-8");
      //响应给前端
        response.getWriter().println(new ObjectMapper().writeValueAsString(map));
      return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

配置拦截器

package com.qiumin.config;

import com.qiumin.interceptor.JwtInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author qiumin
 * @classname InterceptorConfig
 * @Description love code
 * @date 2022-07-14 13:37
 */

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JwtInterceptor())
                .addPathPatterns("/user/test2")  //拦截的路径请求
                .excludePathPatterns("/user/login");  //放行的请求路径
    }
}


参考文章:https://blog.csdn.net/m0_57752520/article/details/125785908
如有问题可联系博主

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

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

相关文章

前端报错adding CSS “touch-action: none“ to this element解决方案

目录 如图所示控制台出现报错&#xff1a; 原因&#xff1a; touch-action 介绍&#xff1a; 解决方案&#xff1a; 1.手动设置touch-action&#xff1a; 2.使用条件渲染&#xff1a; 3.CSS样式隔离&#xff1a; 4.浏览器兼容性&#xff1a; 5. 忽略警告 如图所示控制台…

持续集成04--Jenkins结合Gitee创建项目

前言 在持续集成/持续部署&#xff08;CI/CD&#xff09;的旅途中&#xff0c;Jenkins与版本控制系统的紧密集成是不可或缺的一环。本篇“持续集成03--Jenkins结合Gitee创建项目”将引导如何将Jenkins与Gitee&#xff08;一个流行的Git代码托管平台&#xff09;相结合&#xff…

华为USG6000V防火墙安全策略用户认证

目录 一、实验拓扑图 二、要求 三、IP地址规划 四、实验配置 1&#x1f923;防火墙FW1web服务配置 2.网络配置 要求1&#xff1a;DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 要求2&#xff1a;生产区不…

手机误删图片怎么办?2个照片恢复大师来帮忙,轻松找回

手机照片早已成为我们日常生活中的一部分&#xff0c;记录着欢笑、泪水等各种瞬间。但有时候&#xff0c;因为各种原因&#xff0c;它们会突然消失&#xff0c;让人痛心疾首。照片恢复有哪些方法呢&#xff1f;别急&#xff0c;今天就给大家带来2位照片恢复大师&#xff0c;它们…

中国姓名学大师排行榜,山东济南最有名的起名大师是谁

在2024年揭晓的中国姓名学领域&#xff0c;一场声势浩大的评选活动吸引了无数目光——寻找国内最杰出的起名大师。在这场激烈的竞争中&#xff0c;山东济南的颜廷利教授以其深厚的易学功底和卓越的命名技艺&#xff0c;荣获“中国姓名学十大权威专家”榜首位置&#xff0c;成为…

【深度学习】BeautyGAN: 美妆,化妆,人脸美妆

https://www.sysu-hcp.net/userfiles/files/2021/03/01/3327b564380f20c9.pdf 【深度学习】BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversaria…

NSSCTF中24网安培训day2中web题目【下】

[NISACTF 2022]easyssrf 这道题目考察的是php伪协议的知识点 首先利用file协议进行flag查找 file:///flag.php 接着我们用file协议继续查找fl4g file:///fl4g 接着我们访问此文件&#xff0c;得到php代码如下 这里存在着stristr的函数&#x…

AI视频教程下载-ChatGPT速成课程:工作中的ChatGPT入门

使用ChatGPT提升你的生产力&#xff1a;利用OpenAI的革命性ChatGPT模型。 你准备好深入人工智能交流的世界&#xff0c;彻底改变你的职业生涯了吗&#xff1f;本课程适合技术背景和非技术背景的人士&#xff0c;它以独特、有趣且专业的方式&#xff0c;教授如何使用OpenAI的Ch…

【鸿蒙OS】【ArkUI】鸿蒙OS UI布局适配终极攻略

鸿蒙OS UI布局适配终极攻略 像素适配大法&#xff0c;此方法也适合Android ArkUI为开发者提供4种像素单位&#xff0c;框架采用vp为基准数据单位。 vp相当于Android里的dp fp相当于Android里的sp 官方是如何定义的呢,如下图 今天我来教大家如何用PX做到ArkUI的终级适配&…

【python】Pandas 运行报错分析:KeyError: Label not found

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Docker基本讲解及演示

Docker安装教程 Docker安装教程 1、Docker介绍 Docker是一个开源的应用容器引擎&#xff0c;允许开发者将应用程序及其依赖项打包成一个轻量级、可移植的容器&#xff0c;然后发布到任何支持 Docker 的环境中运行&#xff0c;无论是开发机、测试机还是生产环境。 Docker基于…

CentOS 7 网络配置

如想了解请查看 虚拟机安装CentOS7 第一步&#xff1a;查看虚拟机网络编辑器、查看NAT设置 &#xff08;子网ID&#xff0c;网关IP&#xff09; 第二步&#xff1a;配置VMnet8 IP与DNS 注意事项&#xff1a;子网掩码与默认网关与 第一步 保持一致 第三步&#xff1a;网络配置…

EXCEL VBA工程密码破解 工作表保护破解

这里写目录标题 破解Excel宏工程加密方法一 新建破解宏文件方法二 修改二进制文件 破解工作表保护引用 破解Excel宏工程加密 如图所示 白料数据处理已工程被加密。 方法一 新建破解宏文件 1 创建一个XLSM文件&#xff0c;查看代码 ALTF11 2 新建一个模块&#xff0c;“插…

打包一个自己的Vivado IP核

写在前面 模块复用是逻辑设计人员必须掌握的一个基本功&#xff0c;通过将成熟模块打包成IP核&#xff0c;可实现重复利用&#xff0c;避免重复造轮子&#xff0c;大幅提高我们的开发效率。 接下来将之前设计的串口接收模块和串口发送模块打包成IP核&#xff0c;再分别调用…

Vue+Echarts做图表展示

1.Echarts安装 终端运行安装命令&#xff1a; npm install echarts -s 在main.js做全局引用&#xff1a; //引入echarts import * as echarts from echarts //vue全局注入echarts Vue.prototype.$echarts echarts; 2.页面使用Echarts画柱状图和饼图 效果&#xff1a; 代码展…

Qt各个版本安装的保姆级教程

文章目录 前言Qt简介下载Qt安装包安装Qt找到Qt的快捷方式总结 前言 Qt是一款跨平台的C图形用户界面应用程序开发框架&#xff0c;广泛应用于桌面软件、嵌入式软件、移动应用等领域。Qt的强大之处在于其高度的模块化和丰富的工具集&#xff0c;可以帮助开发者快速、高效地构建出…

esplice老项目(非maven)导入idea问题

解决导入idea显示不正常 老项目导入idea后&#xff0c;显示为如下所示&#xff1a; 显示的不太正常&#xff0c;正常显示为下面这个样子&#xff1a; 解决 非老项目 idea的项目中所有的文件全部变成了.java(已解决) 老项目 以下内容参考&#xff1a;idea导入项目后java文…

阿里云CDN架构技术(一)

CDN补充 cdn内容分发网络&#xff08;content delivery network&#xff0c;cdn&#xff09; 构建在互联网TCP/IP四层模型之上对用户透明的覆盖网。 该网络通过全球范围内分布式部署边缘服务器&#xff0c;将互联网内容从互联网中心缓存到靠近用户的边缘服务器上&#xff0c;…

SymPy,一个可以做数学题的Python库,如何使用SymPy进行微积分计算?

SymPy 是一个 Python 库&#xff0c;用于符号数学。这意味着 SymPy 可以帮助用户执行从基本代数到微积分、方程求解、积分、极限、级数、几何、组合数学、离散数学和量子物理等广泛的数学计算。它允许用户以完全符号化的方式处理数学表达式&#xff0c;而无需将问题转换为数值近…

大模型的“幻觉”克星!被低估的RAG技术

1 RAG与大模型、Prompt、微调的关系 本文主要带大家深入学习一下最近AI领域的重要技术RAG&#xff0c;本文致力于用大白话给大家说明白RAG&#xff0c;但是还是需要一些大模型和微调有关的领域名词有一些基本的了解&#xff0c;大家选择性阅读哦!在进行正文学习之前我们先用一…