神的孩子都在歌唱

神的孩子都在歌唱

前言

公私钥非对称加密 生成和验证JSON Web Token

什么是JSON Web Token (JWT)

JSON Web Token (JWT) 是一种轻量级的身份验证和授权机制,由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。其中头部和载荷都是Base64编码的JSON对象,签名是对头部、载荷和秘钥进行加密生成的。

JWT的优点在于它是一种无状态的身份验证机制,因此可以在分布式系统中广泛使用。JWT通常作为API的身份验证机制,客户端在请求中携带JWT token,服务端通过验证JWT token来确定请求的合法性。

使用JWT作为API的身份验证机制可以避免服务器保存用户登录状态,从而提高系统的可扩展性和安全性。在实际开发中,可以根据具体需求来选择不同的加密算法和秘钥长度。

Java程序中生成和验证JWT

以下是一个Java程序,用于生成和验证JSON Web Token (JWT)。该程序使用了RSA非对称加密算法生成公私钥对,并使用私钥构建JWT token,设置了主题、签发时间、过期时间和一个自定义声明。最后,使用公钥验证JWT token,并从中获取主题信息和自定义声明。

package com.ugdsec.common.auth.common.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

public class JwtExample {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {

        // 生成RSA公私钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
        String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());

        // 将公钥字符串转换为公钥对象
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);

        // 将私钥字符串转换为私钥对象
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        privateKey = KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec);

        // 构建JWT token
        String jwtToken = Jwts.builder()
            .setSubject("user")
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000))
            .signWith(SignatureAlgorithm.RS256, privateKey)
            .claim("test","sdfs")
            .compact();
        System.out.println(jwtToken);

        // 验证JWT token
        Jws<Claims> jws = Jwts.parser()
            .setSigningKey(publicKey)
            .parseClaimsJws(jwtToken);

        // 获取JWT token中的主题信息和自定义声明
        String subject = jws.getBody().getSubject();
        String test = (String) jws.getBody().get("test");
        System.out.println("Subject: " + subject);
        System.out.println("Test: " + test);
    }
}

输出结果:

公私钥非对称加密 生成和验证JSON Web Token (JWT)-LMLPHP

代码解析

程序中使用了io.jsonwebtoken包提供的类和方法来生成和验证JWT token。具体分析如下:

  1. 导入所需的包
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
  1. 生成RSA公私钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded());
String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded());

使用KeyPairGenerator类生成2048位的RSA公私钥对,将公私钥分别存储在publicKeyprivateKey变量中,并将它们对应的字符串分别存储在publicKeyStringprivateKeyString变量中。

  1. 将公私钥字符串转换为公私钥对象
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyString);
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
publicKey = KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);

byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyString);
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
privateKey = KeyFactory.getInstance("RSA").generatePrivate(privateKeySpec);

将公私钥对应的字符串转换成公私钥对象,以便后续使用。

  1. 构建JWT token
String jwtToken = Jwts.builder()
    .setSubject("user")
    .setIssuedAt(new Date())
    .setExpiration(new Date(System.currentTimeMillis() + 3600000))
    .signWith(SignatureAlgorithm.RS256, privateKey)
    .claim("test","sdfs")
    .compact();
System.out.println(jwtToken);

使用Jwts.builder()方法构建JWT token,设置了主题、签发时间、过期时间和一个自定义声明,并使用私钥进行签名。

  1. 验证JWT token
Jws<Claims> jws = Jwts.parser()
    .setSigningKey(publicKey)
    .parseClaimsJws(jwtToken);

使用公钥验证JWT token,并将解析后的结果存储在jws变量中。

  1. 获取JWT token中的主题信息和自定义声明
String subject = jws.getBody().getSubject();
String test = (String) jws.getBody().get("test");
System.out.println("Subject: " + subject);
System.out.println("Test: " + test);
09-21 03:28