从零开发短视频电商 使用nimbus-jose-jwt进行对称签名和非对称签名的JWT实现

这篇具有很好参考价值的文章主要介绍了从零开发短视频电商 使用nimbus-jose-jwt进行对称签名和非对称签名的JWT实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

JWT的基础介绍可以参见这个地址:https://jwt.io/introduction,下面都是从上面摘录的。

什么是JSON Web Token

JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于安全地在各方之间传输信息,其格式为JSON对象。这些信息可以被验证和信任,因为它们是数字签名的。

JWT可以使用对称算法(使用HMAC算法)或非对称算法(使用RSA或ECDSA的公钥/私钥)对进行签名。

尽管JWT可以加密以实现机密性(JWK),但我们更多使用的是签名令牌(JWS)。

  • 签名令牌可以验证声明的完整性,而加密令牌则隐藏这些声明,不让其他方看到。
  • 使用公钥/私钥对进行签名时,签名还证明只有持有私钥的一方才是签名者。

何时使用JSON Web Token

以下是一些适用于JSON Web Tokens的常见场景:

  • 授权:这是使用JWT的最常见场景。一旦用户登录,每个后续请求都会包含JWT,允许用户访问受该令牌允许的路由、服务和资源。单点登录是一种广泛使用JWT的功能,因为它的开销很小,并且可以轻松地在不同域之间使用。

  • 信息交换:JSON Web Tokens是安全地在各方之间传输信息的良好方式。因为JWT可以进行签名,例如使用公钥/私钥对,所以您可以确信发送方就是它们所声称的那个。此外,由于签名是使用头部和负载计算的,您还可以验证内容是否被篡改。

JSON Web Token的结构是什么

在其紧凑形式中,JSON Web Token由三个由点(.)分隔的部分组成,它们是:

  • 头部(Header)
  • 负载(Payload)
  • 签名(Signature)

因此,一个JWT通常为:xxxxx.yyyyy.zzzzz

让我们逐个解释不同的部分。

头部(Header)

头部通常由两部分组成:令牌类型(JWT)和所使用的签名算法,例如HMAC SHA256RSA

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

然后,对该 JSON 进行Base64Url编码以形成 JWT 的第一部分。

负载(Payload)

令牌的第二部分是有效载荷,其中包含声明(claims)。声明是关于实体(通常是用户)和附加数据的陈述。有三种类型的声明:注册声明、公共声明和私有声明。

  • 注册声明:这是一组预定义的声明,它们不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。其中一些包括:iss(发行人)、exp(过期时间)、sub(主题)、aud(受众)等。

请注意,声明名称只有三个字符长,因为JWT旨在紧凑。

  • 公共声明:这些声明可以由使用JWT的人自由定义。但为了避免冲突,它们应在IANA JSON Web Token注册表中定义,或者定义为包含冲突安全命名空间的URI。

  • 私有声明:这些是自定义的声明,用于在同意使用它们的各方之间共享信息,既不是注册声明也不是公共声明。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后通过Base64Url编码,形成JSON Web Token的第二部分。

请注意,对于已签名的令牌,尽管受到篡改的保护,但任何人都可以读取此信息。除非进行加密,否则不要将机密信息放在JWT的有效载荷或头部元素中。

签名(Signature)

要创建签名部分,您需要获取编码的头部、编码的有效载荷、一个密钥、头部中指定的算法,并对其进行签名。

例如,如果您想使用HMAC SHA256算法,签名将按以下方式创建:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

签名用于验证消息在传递过程中是否被更改,并且对于使用私钥签名的令牌,还可以验证JWT的发送者身份。

拼接起来

输出是由点分隔的三个Base64-URL字符串,可以在HTML和HTTP环境中轻松传递,与基于XML的标准(如SAML)相比更紧凑。

以下是一个具有先前编码的头部和有效载荷,并使用密钥签名的JWT的示例。

从零开发短视频电商 使用nimbus-jose-jwt进行对称签名和非对称签名的JWT实现,《?从零开发短视频电商》,数据库,java,mysql

如何使用JSON Web Token

在身份验证中,当用户使用其凭据成功登录时,将返回 JSON Web 令牌。需要注意的是,不应将JWT保存的时间超过必要的时间,因为它们是需要保护的凭据。此外,由于安全性的缺乏,应避免将敏感会话数据存储在浏览器存储中。

令牌传输:当用户想要访问受保护的路由或资源时,通常将JWT包含在请求中,放置在授权头部中,使用Bearer方案。头部的内容应如下所示:

Authorization: Bearer <token>

服务器的受保护路由会检查授权头部中是否存在有效的JWT,如果存在,则允许用户访问受保护的资源。如果JWT包含必要的数据,则可以减少某些操作对数据库的查询需求,尽管这并非总是如此。

请注意,如果通过HTTP头部发送JWT令牌,应尽量防止其过大。某些服务器不接受超过8 KB的头部。

工具库

可以在这个网址查找比较权威好用的工具库。

  • maven: com.auth0 / java-jwt / 3.3.0
  • maven: io.jsonwebtoken / jjwt-root / 0.11.1
  • maven: com.nimbusds / nimbus-jose-jwt / 5.7

大部分都是使用上面3个中的某一个,我们这里使用nimbus-jose-jwt。

文档:https://connect2id.com/products/nimbus-jose-jwt

依赖

<dependency>
  <groupId>com.nimbusds</groupId>
  <artifactId>nimbus-jose-jwt</artifactId>
  <version>9.31</version>
</dependency>
<!-- 如果您正在使用以下情况,请取消注释下面的依赖项:
     - JDK 10或更早版本,并且您想要使用RSASSA-PSS(PS256、PS384、PS512)签名算法。
     - JDK 10或更早版本,并且您想要使用EdECDH(X25519或X448)椭圆曲线迪菲-赫尔曼密钥交换加密。
     - JDK 14或更早版本,并且您想要使用EdDSA(Ed25519或Ed448)椭圆曲线签名算法。
     在JDK 15或更高版本上,这些算法是不必要的。
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
    <scope>runtime</scope>
</dependency>
-->

最新版本

流程

对称签名

加签示例

// 生成对称加密密钥
 byte[] sharedKey = "YourSharedKey-122345678sahkjhjkasdfasdf".getBytes();

// 创建一个JWT对象
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().subject("user123")
                // 设置过期时间为当前时间后的一分钟
                .expirationTime(new Date(System.currentTimeMillis() + 60 * 1000)).build();

JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256).build();
SignedJWT signedJWT = new SignedJWT(header, claimsSet);

// 创建HMAC签名器
JWSSigner signer = new MACSigner(sharedKey);

// 对JWT进行签名
signedJWT.sign(signer);

// 将JWT序列化为字符串
String jwtString = signedJWT.serialize();

System.out.println("JWT Token: " + jwtString);

验签示例

// 生成对称加密密钥
 byte[] sharedKey = "YourSharedKey-122345678sahkjhjkasdfasdf".getBytes();

// 解析JWT字符串
String jwtString = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2ODg1NDY2MDAsInN1YiI6InVzZXIxMjMifQ.3mGtNjwt6Z50DhEeBv2zo9qi8aHGh9Mu2RWLVeH0FE8";
SignedJWT signedJWT = SignedJWT.parse(jwtString);
// 创建HMAC验证器
JWSVerifier verifier = new MACVerifier(sharedKey);
// 验证JWT签名
boolean isValid = signedJWT.verify(verifier);

if (isValid) {
      System.out.println("JWT signature is valid.");
      // 获取JWT的声明
      JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();
      System.out.println("Subject: " + claimsSet.getSubject());
      System.out.println("Expiration Time: " + claimsSet.getExpirationTime());

      if (!signedJWT.getJWTClaimsSet().getExpirationTime().after(new Date())) {
                System.out.println("JWT signature is expired.");
        }
} else {
            System.out.println("JWT signature is not valid.");
}

非对称签名

RSA算法和ECDSA (Elliptic Curve Digital Signature Algorithm)算法是常用的非对称加密算法,用于生成和验证数字签名。

RSA算法是基于大素数分解的数论问题。它使用一对公钥和私钥来进行加密和解密操作,同时也可以用于生成和验证数字签名。RSA算法在安全性和广泛应用上都有很好的表现,但由于其计算复杂性,对于大数据量的加密和解密操作可能会比较耗时

ECDSA算法基于椭圆曲线离散对数问题。相比于RSA算法,ECDSA算法使用更短的密钥长度,提供相同的安全性水平。这使得ECDSA算法在资源受限的环境中更具优势,如移动设备和物联网设备。ECDSA算法还具有更快的加密和解密速度

如何生成EC384公私钥

方式一

// Generate an EC key pair
ECKey ecJWK = new ECKeyGenerator(Curve.P_384)
                .keyID("123")
                .generate();
ECPublicKey ecPublicKey = ecJWK.toECPublicKey();
ECPrivateKey ecPrivateKey = ecJWK.toECPrivateKey();
// 将公钥编码为Base64字符串
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
// 将私钥编码为Base64字符串
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded())    

//  或者
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;

// 生成ECDSA密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
keyPairGenerator.initialize(384); // 使用EC384曲线
KeyPair keyPair = keyPairGenerator.generateKeyPair();

// 获取私钥和公钥
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();

// 打印私钥和公钥
System.out.println("Private Key: " + privateKey);
System.out.println("Public Key: " + publicKey);
// 将公钥编码为Base64字符串
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
// 将私钥编码为Base64字符串
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded())    

publicKeyBase64: MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEVT+YNmKBnvXtS11FvcKe7tBHi3aAbvk87+tBGFadfHM/zy1+Q4EjlXjbLhhl1LNPup5BHhQBG+jKRP0/Rvoy0LiNmDdX9MqC0xvTtefFKBL4CsM0vlViObOUNxumzxMH
privateKeyBase64: ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDDAaCeLDnCRmkmZ8vs7nlnApCxBIL2RyizpY4jh1VE5Svr4d92AwjZyrt5Szl8AvPE=

方式二

openssl ecparam -list_curves
# 生成私钥
openssl ecparam -genkey -name secp384r1 -noout -out ec384-private.pem
# 根据私钥生成公钥
openssl ec -in ec384-private.pem -pubout -out ec384-public.pem
# 把私钥转换为PKCS8格式
openssl pkcs8 -topk8 -nocrypt -in ec384-private.pem -out ec384-private.pem_pkcs8.pem
# 注意
publicKeyBase64 = ec384-public.pem中的字符串
privateKeyBase64 = ec384-private.pem_pkcs8.pem中的字符串

从零开发短视频电商 使用nimbus-jose-jwt进行对称签名和非对称签名的JWT实现,《?从零开发短视频电商》,数据库,java,mysql

序列化,反序列化和传输公私钥

注意,私钥一定是颁发者自己好好保存,公钥的话无所谓,公钥本来就是要公开的。可以通过微信邮件等传输。

ECDSA公钥可以以多种格式进行存储和传输。以下是使用Base64编码的示例:

// 假设已经有Base64编码的公钥和私钥字符串
String publicKeyBase64 = "YourBase64EncodedPublicKey";
String privateKeyBase64 = "YourBase64EncodedPrivateKey";
// 将Base64字符串解码为字节数组
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);

// 创建公钥的KeySpec对象
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);

// 创建私钥的KeySpec对象
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);

// 使用KeyFactory生成公钥和私钥对象
KeyFactory keyFactory = KeyFactory.getInstance("EC");
ECPublicKey publicKey = (ECPublicKey) keyFactory.generatePublic(publicKeySpec);
ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(privateKeySpec);

System.out.println("Public Key: " + publicKey);
System.out.println("Private Key: " + privateKey);

加签示例

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;

// 创建一个JWT对象
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
        .subject("user123")
        .expirationTime(new Date(new Date().getTime() + 60 * 1000)) // 设置过期时间为当前时间后的一分钟
        .build();

JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.ES384)
        .build();

SignedJWT signedJWT = new SignedJWT(header, claimsSet);

// 创建ECDSA私钥签名器
JWSSigner signer = new ECDSASigner(privateKey);

// 对JWT进行签名
signedJWT.sign(signer);

// 将JWT序列化为字符串
String jwtString = signedJWT.serialize();

System.out.println("JWT Token: " + jwtString);

验签示例

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.*;

// 解析JWT字符串
SignedJWT signedJWT = SignedJWT.parse(jwtString);

// 创建ECDSA公钥验证器
JWSVerifier verifier = new ECDSAVerifier(publicKey);

// 验证JWT签名
boolean isValid;
try {
    isValid = signedJWT.verify(verifier);
} catch (JOSEException e) {
    isValid = false;
}

if (isValid) {
    System.out.println("JWT signature is valid.");

    // 获取JWT的声明
    JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();
    System.out.println("Subject: " + claimsSet.getSubject());
    System.out.println("Expiration Time: " + claimsSet.getExpirationTime());
} else {
    System.out.println("JWT signature is not valid.");
}

总结

对称签名适用于以下情况:

  1. 快速性能要求:对称签名算法通常比非对称签名算法更快,因为它们使用相同的密钥进行签名和验证。
  2. 内部通信:当签名用于内部通信,不需要在不同的实体之间共享密钥时,对称签名是一种简便的选择。
  3. 密钥管理:对称签名只需要管理一个密钥,而非对称签名需要管理公钥和私钥对。

非对称签名适用于以下情况:文章来源地址https://www.toymoban.com/news/detail-526299.html

  1. 安全性要求:非对称签名提供更高的安全性,因为它使用不同的密钥进行签名和验证,私钥保持私密,公钥可公开共享。
  2. 跨网络通信:当签名用于跨网络通信,需要在不同的实体之间共享公钥时,非对称签名是更安全的选择。
  3. 数字证书:非对称签名用于生成和验证数字证书,以确保通信的身份验证和数据的完整性。

到了这里,关于从零开发短视频电商 使用nimbus-jose-jwt进行对称签名和非对称签名的JWT实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开发短视频电商 Java开发者的AI大模型(LLM)应用开发和设计-LangChain4j

    Github : https://github.com/langchain4j https://github.com/langchain4j/langchain4j https://github.com/langchain4j/langchain4j-embeddings https://github.com/langchain4j/langchain4j-examples Java版 langchain , 利用LLMs的力量增强你的java应用程序。 该项目的目标是简化 AI/LLM 功能到 Java 应用程序的集成。 可以通过以下方式实

    2024年01月16日
    浏览(33)
  • 从零搭建仿抖音短视频APP-后端开发短视频业务模块(1)

    项目持续更新中: 仿抖音短视频APP专栏 目录 发布短视频的流程梳理 传统上传流程  传统上传 CDN上传 CDN上传流程 使用Unicloud云端功能  实现app端视频上传 保存视频信息入库 注:controller接受到文件之后会把文件上传到服务器,同时controller获得某一帧帧来获得我们的封面图,

    2023年04月12日
    浏览(35)
  • 【学习】从零开发的Android音视频开发(13)——MediaCodec到OMX框架过程及其硬解码

    在讲NuPlayer时,NuPlayer解码部分会创建MediaCodec,并且最终到达OMX框架,先看MediaCodec的 init 函数 从init函数中可以看到,首先创建了 ACodec ,并且初始化了 ALooper 、 AMessage ,由于ACodec继承自 AHandler ,那么一套消息机制就有了。最后发送 kWhatInit 消息,收到消息的逻辑位于ACodec.

    2023年04月08日
    浏览(37)
  • C++&Python&C# 三语言OpenCV从零开发(4):视频流读取

    C++PythonCsharp in OpenCV 专栏 【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程(附带课程课件资料+课件笔记) OpenCV 教程中文文档|OpenCV中文 OpenCV教程中文文档|W3Cschool OpenCV基础教程——视频的读取与写入(超详细+附代码) 我之前写过一篇基于Python的,我现在重新写一次

    2024年01月21日
    浏览(49)
  • 从零开始搭建仿抖音短视频APP-后端开发消息业务模块(1)

    项目持续更新中: 仿抖音短视频APP专栏 目录 保存系统消息到MongoDB 系统消息入库保存-关注 系统消息入库保存-点赞短视频 系统消息入库保存-评论与回复 我们把mongoDB整合到Springboot之后,我们需要把映射层面做好。 首先在model创建一个新的对象层面,也就是一个新的包: 我

    2024年02月01日
    浏览(40)
  • 【学习】从零开始的Android音视频开发(3)——MediaPlayer的prepare/prepareAsync流程和start流程

    在之前的流程中我们没有从MediaPlayer生态上认识各类库之间的依赖调用关系 MediaPlayer部分头文件在frameworks/base/include/media/目录中,这个目录和libmedia.so库源文件的目录frameworks/av/media/libmedia/相对应。主要头文件有 IMediaPlayerClient.h、mediaplayer.h、IMediaPlayer.h、IMediaPlayerService.h、Med

    2024年02月03日
    浏览(30)
  • [从零开始学DeepFaceLab-12]: 使用-命令行八大操作步骤-第8步:把图片合成视频

    目录 总体流程: 步骤8:把图片合成视频 8.1 命令:【8) merged to avi.bat】--

    2023年04月08日
    浏览(24)
  • 吸烟检测从零开始使用YOLOv5+PyQt5+OpenCV实现(支持图片、视频、摄像头实时检测)

    全流程 教程,从数据采集到模型使用到最终展示。若有任何疑问和建议欢迎评论区讨论。 先放上最终实现效果 检测效果 由上图我们可以看到,使用YOLOV5完成了吸烟的目标识别检测,可以达到mAP可达85.38%。通过对吸烟的自动检测可以方便商场、医院、疗养院等公共场合进行禁

    2024年02月09日
    浏览(41)
  • 烟雾和火灾检测从零开始使用YOLOv5+PyQt5+OpenCV实现(支持图片、视频、摄像头实时检测)

    全流程 教程,从数据采集到模型使用到最终展示。若有任何疑问和建议欢迎评论区讨论。 先放上最终实现效果 图片检测效果 视频检测效果 针对住宅、加油站、公路、森林等火灾高发场景,可以自动检测监控区域内的烟雾和火灾,帮助相关人员及时应对,最大程度降低人员

    2024年02月11日
    浏览(39)
  • 【从零开始的rust web开发之路 一】axum学习使用

    第一章 axum学习使用 本职java开发,兼架构设计。空闲时间学习了rust,目前还不熟练掌握。想着用urst开发个web服务,正好熟悉一下rust语言开发。 目前rust 语言web开发相关的框架已经有很多,但还是和java,go语言比不了。 这个系列想完整走一遍web开发,后续有时间就出orm,还

    2024年02月12日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包