一、前言

针对前后端分离的项目,大多是通过 token 进行身份认证来进行交互,今天将介绍一种简单的创建 token 的方式 -- JWT。

二、基本介绍

2.1 定义

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。

2.2 组成部分

一个 JWT 实际上就是一个字符串,它由三部分组成,头部、载荷与签名。前两部分需要经过 Base64 编码,后一部分通过前两部分 Base64 编码后再加密而成。

如果读者不理解上边的陈述,不要紧,下文会详细讲解。

头部(Header)

头部用于描述关于该 JWT 的最基本的信息,例如其类型以及签名所用的算法等,也可以被表示成一个 JSON 对象。例如:

{"typ":"JWT","alg":"HS256"}

在头部指明了签名算法是 HS256 算法。

经过 Base64 编码得到:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9(第一部分)。下文参考资料提供线上加密/解密网址,感兴趣的读者可以自己尝试。

载荷(playload)

载荷就是存放有效信息的地方。这些有效信息包含三个部分:

(1)标准中注册的声明(建议但不强制使用)

iss: jwt签发者

sub: jwt所面向的用户

aud: 接收jwt的一方

exp: jwt的过期时间,这个过期时间必须要大于签发时间

nbf: 定义在什么时间之前,该jwt都是不可用的.

iat: jwt的签发时间

jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

(2)公共的声明

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密。

例如:

{"id":"123456","name":"MoonlightL","sex":"male"}

将该 json 字符串进行 Base64 编码得到:eyJpZCI6IjEyMzQ1NiIsIm5hbWUiOiJNb29ubGlnaHRMIiwic2V4IjoibWFsZSJ9(第二部分)。

(3)私有的声明

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64 是对称解密的,意味着该部分信息可以归类为明文信息。

注意:载荷中的这3个声明并不是都要同时设置。

签证(signature)

jwt的第三部分是一个签证信息。

这个部分需要 Base64 加密后的 header 和 Base64 加密后的 payload 使用 “.” 连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后就构成了 jwt 的第三部分。

即将 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEyMzQ1NiIsIm5hbWUiOiJNb29ubGlnaHRMIiwic2V4IjoibWFsZSJ9 进行 HS256 算法加密(header 定义的)得到:

e5dda3f17226c1c6ca7435cd17f83ec0c74d62bd8e8386e1a178cd970737f09f(第三部分)。

最后,我们将上述的 3 个部分的字符串通过 “.” 进行拼接得到 JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEyMzQ1NiIsIm5hbWUiOiJNb29ubGlnaHRMIiwic2V4IjoibWFsZSJ9.e5dda3f17226c1c6ca7435cd17f83ec0c74d62bd8e8386e1a178cd970737f09f 。

为了验证上述生成的 jwt 是否合法,我们可以登录 JWT 官网,官网界面提供 JWT 解密功能,将生成好的 JWT 复制到如下图中进行解密:

在实际开发中,用户登录成功后,后端生成 jwt 返回给前端,之后,前端与后端交互时携带 jwt 让后端验证 jwt 的合法性。

三、实战入门

通过上述的介绍,我们已经了解到什么是 JWT 以及 JWT 生成的规则,现在我们通过代码方式来生成 JWT。

JWT 官网提供了通过不同编程语言来创建 JWT 的工具类/库,此次测试我们选用 JJWT 。

3.1 添加依赖

io.jsonwebtoken

jjwt-api

0.10.5

io.jsonwebtoken

jjwt-impl

0.10.5

runtime

io.jsonwebtoken

jjwt-jackson

0.10.5

runtime

3.2 编码

import java.security.Key;

import java.util.Date;

import java.util.UUID;

import org.junit.Test;

import io.jsonwebtoken.Claims;

import io.jsonwebtoken.Jws;

import io.jsonwebtoken.JwtBuilder;

import io.jsonwebtoken.JwtException;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import io.jsonwebtoken.security.Keys;

public class JWTTest {

@Test

public void testJWT() {

Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

System.out.println("=============创建 JWT===========");

Date now = new Date();

JwtBuilder builder= Jwts.builder()

.setId(UUID.randomUUID().toString()) // 载荷-标准中注册的声明

.setSubject("admin") // 载荷-标准中注册的声明

.setIssuedAt(now) // 载荷-标准中注册的声明,表示签发时间

.claim("id", "123456") // 载荷-公共的声明

.claim("name", "MoonlightL") // 载荷-公共的声明

.claim("sex", "male") // 载荷-公共的声明

.signWith(key); // 签证

String jwt = builder.compact();

System.out.println("生成的 jwt :" +jwt);

System.out.println("=============解析 JWT===========");

try {

Jws result = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt);

// 以下步骤随实际情况而定,只要上一行代码执行不抛异常就证明 jwt 是有效的、合法的

Claims body = result.getBody();

System.out.println("载荷-标准中注册的声明 id:" + body.getId());

System.out.println("载荷-标准中注册的声明 subject:" + body.getSubject());

System.out.println("载荷-标准中注册的声明 issueAt:" + body.getIssuedAt());

System.out.println("载荷-公共的声明的 id:" + result.getBody().get("id"));

System.out.println("载荷-公共的声明的 name:" + result.getBody().get("name"));

System.out.println("载荷-公共的声明的 sex:" + result.getBody().get("sex"));

} catch (JwtException ex) { // jwt 不合法或过期都会抛异常

ex.printStackTrace();

}

}

}

执行结果:

=============创建 JWT===========

生成的 jwt :eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI3ZjZmZjRlMC04YjM5LTQyYjUtOGRkNS0xN2M4ZjM5ZmZhNzMiLCJzdWIiOiJhZG1pbiIsImlhdCI6MTU0MzIwNTI4OSwiZXhwIjoxNTQzMjA1MzQ5LCJpZCI6IjEyMzQ1NiIsIm5hbWUiOiJNb29ubGlnaHRMIiwic2V4IjoibWFsZSJ9.BtEi-GCj5mCunXD_g0Cra7CSE_bMxhTzlOELWKc17I8

=============解析 JWT===========

载荷-标准中注册的声明 id:7f6ff4e0-8b39-42b5-8dd5-17c8f39ffa73

载荷-标准中注册的声明 subject:admin

载荷-标准中注册的声明 issueAt:Mon Nov 26 12:08:09 CST 2018

载荷-公共的声明的 id:123456

载荷-公共的声明的 name:MoonlightL

载荷-公共的声明的 sex:male

注意:加密和解密 JWT 必须是同一个 Key 对象

注意:解密 JWT 时,必须要抓取 JwtException 异常,只要抓取到该异常说明该 JWT 不可用了

JJWT 库还有其他使用方式,具体资料请查看下边提供的参考资料。

四、参考资料

jwt如何加盐_JWT 基础教程相关推荐

  1. SpringBoot 系列教程(八十五):Spring Boot使用MD5加盐验签Api接口之前后端分离架构设计

    加密算法参考: 浅谈常见的七种加密算法及实现 加密算法参考: 加密算法(DES,AES,RSA,MD5,SHA1,Base64)比较和项目应用 目的: 通过对API接口请求报文签名,后端进行验签处理, ...

  2. Spring Cloud Alibaba基础教程:Nacos配置的多文件加载与共享配置

    <Spring Cloud Alibaba基础教程>连载中,关注我一起学期!前情回顾: <使用Nacos实现服务注册与发现> <支持的几种服务消费方式> <使 ...

  3. Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解

    <Spring Cloud Alibaba基础教程>连载中,关注我一起学期!前情回顾: <使用Nacos实现服务注册与发现> <支持的几种服务消费方式> <使 ...

  4. QGIS基础教程 (入门级)——下载安装、新建工程、加载数据

    QGIS基础教程(一) 本教程内容相对基础,面向从未使用过QGIS或相似GIS软件人群 第一节 QGIS下载安装,新建工程,加载数据 1. 下载及安装 官网下载:QGIS下载网址 注意:下载长期版,比 ...

  5. java swing(GUI图形化界面)基础教程3-添加事件监听1

    学习此内容前建议先去学习java基础知识: 匿名内部类 (学的多的可以用lambda表达式,更加简便) 好, 我们先看一下之前的代码(即一个窗口和一个按钮) 如果想看详细内容,链接为: (23条消息) ...

  6. MC基础教程#2 加载器、模组、光影、材质包、数据包下载及安装(国际Java版)

    MC基础教程系列第二期出了 和上一期隔了两年- 加载器 下载 Forge 老牌加载器,新版本( 1.13+ )不太好用 官网: https://files.minecraftforge.net/net ...

  7. DirectX12(D3D12)基础教程(二十二) ——HDR IBL 等距柱面环境光源加载和解算及 GS 一次性渲染到 CubeMap

    前序文章目录 DirectX12(D3D12)基础教程(一)--基础教程 DirectX12(D3D12)基础教程(二)--理解根签名.初识显存管理和加载纹理.理解资源屏障 DirectX12(D3D ...

  8. 批量加水印加logo#ps入门基础教程学习ps视频教程

    批量加水印加logo#ps入门基础教程学习ps视频教程修图后期

  9. SpringBoot Security 自定义登录验证逻辑+密码加盐

    密码加盐思路 JAVA 加盐加密方法_Teln_小凯的博客-CSDN博客 盐加密方法 @ApiOperation(value = "002-加密")@PreAuthorize(&q ...

  10. c语言常量类型转换,c语言基础教程常量变量和类型转换,免费版.doc

    c语言基础教程常量变量和类型转换,免费版 第二章??????常量变量和类型转换2.1.1数字常量??? 数字常量包括整型常量和浮点型常量,浮点型常量又称实数.????1.整型常量???? HYPERL ...

最新文章

  1. 第一节 并发基础概念及实现、进程、线程基本概念
  2. SVN服务器搭建--Subversio与TortoiseSVN的配置安装
  3. 系统性能优化的常见八大误区
  4. jvm性能调优 - 10白话年轻代数据晋升老年代规则及老年代回收算法
  5. Google、Azure、阿里云、RedHat…全球的 K8s 圈大佬聚在一起要聊啥?
  6. 转:自定义谷歌地图配色方案
  7. 使用Spring Cloud休息客户电话
  8. Canvas or SVG?一张好图,两手准备,就在 ECharts 4.0
  9. 电气器件系列三十三:步进电机驱动器
  10. Microbiome | 黄海所陈松林院士/华科宁康等-肠道菌群在龙利鱼(半滑舌鳎)抗弧菌病性状形成中的机制...
  11. python中的re模块
  12. 【02】一个实现h5的拖放的整个过程-魔芋
  13. 模电——三极管各个引脚之间的电压关系
  14. 3D结构光摄像头深度算法 转载
  15. Canal 及canal.admin(v1.1.5)踩坑记录
  16. 看WIZ110SR如何实现串口转以太网功能
  17. 华为HCNA之配置Trunk实验
  18. ubuntu 制作Mac启动盘
  19. Qt 桌面悬浮画图软件--电子白板
  20. 基于词向量word2vec匹配的英文问答系统

热门文章

  1. torch 默认参数初始化_pytorch的初始化方式总结
  2. python while true循环_python学习——while True的用法
  3. eclipse git拉取失败_收藏!工作中Git使用实践和常用命令流程合集
  4. android 屏幕分辨率 更改
  5. BFS+模拟 ZOJ 3865 Superbot
  6. maven依赖关系中 scope属性含义
  7. Google浏览器Chrome安装失败,错误代码0xa0430721解决办法
  8. hql中 oracle当前时间,hql oracle 比较 日期时间
  9. matlab实现m-k突变的,用matlab进行mk趋势分析与突变检验.pdf
  10. devc 能优化吗_小网站能做seo优化吗?如何为小公司网站做seo优化?