基于Java验证jwt token代码实例

 更新时间:2019年12月20日 09:24:19   作者:白马酒凉  
这篇文章主要介绍了基于Java验证jwt token代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了基于Java验证jwt token代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

How to load public certificate from pem file..?地址

1.HS256对称加密

package jwt;
 
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.Vector;
import java.util.Map;
 
import sun.misc.BASE64Decoder;
 
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
 
 
public class JWTValidator {
  private static String JWT_Type = "JWT";
   
  protected boolean validated;
  protected Object[] claims;
   
  public JWTValidator() {
    setValidated(false);
    setClaims(null);
  }
  public String Generate(String secret, String issuer, String audience, String subject){
    try {
      Algorithm algorithm = Algorithm.HMAC256(secret); // HS256
      String token = JWT.create()
        .withIssuer(issuer)
        .withAudience(audience)
        .withSubject(subject)
        .sign(algorithm);
      System.out.println(token);
      return token;
    } catch (Exception exception){
      //UTF-8 encoding not supported
      return "";
    }
  }
   
 
  public void Validate(String token, String secret, String issuer, String audience, String subject) {
    DecodedJWT jwt = null;
    setValidated(false);
     
    if (token == null || secret == null || issuer == null || audience == null || subject == null)
      return;
     
    try {
      jwt = JWT.require(Algorithm.HMAC256(secret.getBytes())).build().verify(token);
    } catch (JWTVerificationException e) {
      return;
    }
     
    if (jwt == null || jwt.getType() == null || !jwt.getType().contentEquals(JWT_Type))
      return;
     
    if (!jwt.getIssuer().contentEquals(issuer) ||
      !jwt.getAudience().contains(audience) ||
      !jwt.getSubject().contentEquals(subject))
      return;
     
    Date now = new Date();
     
    if ((jwt.getNotBefore() != null && jwt.getNotBefore().after(now)) ||
      (jwt.getExpiresAt() != null && jwt.getExpiresAt().before(now)))
      return;
     
    setValidated(true);
 
    Map<String, Claim> claimsMap = jwt.getClaims();
    Vector<Claim> claimsVector = new Vector<Claim>();
     
    if (claimsMap != null) {
      for (Map.Entry<String, Claim> entry : claimsMap.entrySet()) {
        String key = entry.getKey();
        if (key != null && !key.matches("aud|sub|iss|exp|iat")) {         
          //claimsVector.add(new Claim(key, entry.getValue().asString()));
        }
      }   
    }
 
    setClaims(claimsVector.isEmpty() ? null : claimsVector.toArray());
  }
 
  public boolean isValidated() { return validated; }
  public void setValidated(boolean val) { validated = val; }
 
  public Object[] getClaims() { return claims; }
  public void setClaims(Object[] val) { claims = (val == null ? new Object[0] : val); }
}

2.RS256不对称加密,需要用public cert来验证

package jwt;
 
import junit.framework.TestCase;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
 
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.UUID;
 
public class JWTValidatorForRSA extends TestCase{
 
  public void testCreateToken() throws IOException {
    System.out.println(createToken());
  }
 
  public void testVerifyToken() throws Exception {
    String token = createToken();
    System.out.println(token);
     
    String pkeyPath = "D:\\temp\\idsrv4.crt";
    JwtClaims jwtClaims = verifyToken(token,pkeyPath);
    System.out.println(jwtClaims.getClaimValue("name"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(jwtClaims.getIssuedAt().getValueInMillis()));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(jwtClaims.getExpirationTime().getValueInMillis()));
  }
 
  /**
   * 生成jwt,SHA256加密
   * @return
   * @throws IOException
   */
  public String createToken() throws IOException {
    String privateKeyPath = "D:\\temp\\idsrv4.key";
    PrivateKey privateKey = getPrivateKey(getStringFromFile(privateKeyPath));
    final JwtClaims claims = new JwtClaims();
    claims.setClaim("name", "jack");
    claims.setSubject("a@a.com");
    claims.setAudience("test");//用于验证签名是否合法,验证方必须包含这些内容才验证通过
    claims.setExpirationTimeMinutesInTheFuture(-1); // 60*24*30);
    claims.setIssuedAtToNow();
 
    // Generate the payload
    final JsonWebSignature jws = new JsonWebSignature();
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    jws.setPayload(claims.toJson());
    jws.setKeyIdHeaderValue(UUID.randomUUID().toString());
 
    // Sign using the private key
    jws.setKey(privateKey);
    try {
      return jws.getCompactSerialization();
    } catch (JoseException e) {
      return null;
    }
  }
 
  /**
   * 验证jwt
   * @param token
   * @return
   * @throws Exception
   */
  public JwtClaims verifyToken(String token,String publicKeyPath) throws Exception {
 
    try {
      PublicKey publicKey = getPublicKey(publicKeyPath);
 
      JwtConsumer jwtConsumer = new JwtConsumerBuilder()
          .setRequireExpirationTime()
          .setVerificationKey(publicKey)
          .setExpectedAudience("test")//用于验证签名是否合法,可以设置多个,且可设置必须存在项,如果jwt中不包含这些内容则不通过
          .build();
 
      return jwtConsumer.processToClaims(token);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
 
  private String getStringFromFile(String filePath) throws IOException {
    //  生成方法:安装openssl,执行   openssl genrsa -out private.pem 2048
    return IOUtils.toString(new FileInputStream(filePath));
  }
 
  /**
   * 获取PublicKey对象
   * @param publicKeyBase64
   * @return
   * @throws NoSuchAlgorithmException
   * @throws InvalidKeySpecException
   * @throws CertificateException
   * @throws FileNotFoundException
   */
  private PublicKey getPublicKey(String publicKeyPath) throws NoSuchAlgorithmException, InvalidKeySpecException, CertificateException, FileNotFoundException {
    /* Not work : data isn't an object ID (tag = 2)
    String pem = publicKeyBase64
        .replaceAll("\\-*BEGIN.*CERTIFICATE\\-*", "")
        .replaceAll("\\-*END.*CERTIFICATE\\-*", "");
    java.security.Security.addProvider(
        new org.bouncycastle.jce.provider.BouncyCastleProvider()
    );
    System.out.println(pem);
     
    X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(pem));
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
 
    PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
    */
     
    CertificateFactory fact = CertificateFactory.getInstance("X.509");
    FileInputStream is = new FileInputStream (publicKeyPath);
    X509Certificate cer = (X509Certificate) fact.generateCertificate(is);
    PublicKey publicKey = cer.getPublicKey();
     
    System.out.println(publicKey);
     
    return publicKey;
  }
 
  /**
   * 获取PrivateKey对象
   * @param privateKeyBase64
   * @return
   */
  private PrivateKey getPrivateKey(String privateKeyBase64) {
    String privKeyPEM = privateKeyBase64
        .replaceAll("\\-*BEGIN.*KEY\\-*", "")
        .replaceAll("\\-*END.*KEY\\-*", "");
 
    // Base64 decode the data
    byte[] encoded = Base64.decodeBase64(privKeyPEM);
 
    try {
      DerInputStream derReader = new DerInputStream(encoded);
      DerValue[] seq = derReader.getSequence(0);
 
      if (seq.length < 9) {
        throw new GeneralSecurityException("Could not read private key");
      }
 
      // skip version seq[0];
      BigInteger modulus = seq[1].getBigInteger();
      BigInteger publicExp = seq[2].getBigInteger();
      BigInteger privateExp = seq[3].getBigInteger();
      BigInteger primeP = seq[4].getBigInteger();
      BigInteger primeQ = seq[5].getBigInteger();
      BigInteger expP = seq[6].getBigInteger();
      BigInteger expQ = seq[7].getBigInteger();
      BigInteger crtCoeff = seq[8].getBigInteger();
 
      RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp,
          primeP, primeQ, expP, expQ, crtCoeff);
 
      KeyFactory factory = KeyFactory.getInstance("RSA");
      return factory.generatePrivate(keySpec);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot实现权限验证的示例步骤

    SpringBoot实现权限验证的示例步骤

    权限验证是一种用于控制对系统资源和操作的访问的机制。它允许开发人员定义谁可以执行特定操作或访问特定资源,并确保只有经过授权的用户才能执行这些操作,这篇文章主要介绍了SpringBoot实现权限验证,需要的朋友可以参考下
    2023-08-08
  • 高效Java尺寸压缩技巧,节省资源成本

    高效Java尺寸压缩技巧,节省资源成本

    如果你想了解如何优化Java应用程序的尺寸,节省存储空间并提升性能,那么你来对地方了,本指南将教你简单实用的技巧和最佳实践,帮助你轻松减小Java应用程序的体积,让你的代码更高效、更精简,让我们一起开始吧,让Java应用程序变得更小巧而强大!
    2023-12-12
  • maven私服搭建的实现步骤

    maven私服搭建的实现步骤

    本文主要介绍了maven私服搭建的实现步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Java Char的简单工具类CharUtil分享

    Java Char的简单工具类CharUtil分享

    下面小编就为大家分享一篇Java Char的简单工具类CharUtil,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 浅谈Spring Data如何简化数据操作的方法

    浅谈Spring Data如何简化数据操作的方法

    这篇文章主要介绍了看Spring Data如何简化数据操作的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • Spring boot + thymeleaf 后端直接给onclick函数赋值的实现代码

    Spring boot + thymeleaf 后端直接给onclick函数赋值的实现代码

    这篇文章主要介绍了Spring boot + thymeleaf 后端直接给onclick函数赋值的实现代码,需要的朋友可以参考下
    2017-06-06
  • springboot Jpa多数据源(不同库)配置过程

    springboot Jpa多数据源(不同库)配置过程

    这篇文章主要介绍了springboot Jpa多数据源(不同库)配置过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 面试中遇到的java逃逸分析问题

    面试中遇到的java逃逸分析问题

    这篇文章主要介绍了面试中遇到的java逃逸分析问题,逃逸分析(Escape Analysis)简单来讲就是,Java Hotspot 虚拟机可以分析新创建对象的使用范围,并决定是否在 Java 堆上分配内存的一项技术。,需要的朋友可以参考下
    2019-06-06
  • Java比较两个对象大小的三种方法详解

    Java比较两个对象大小的三种方法详解

    在优先级队列中插入的元素必须能比较大小,如果不能比较大小,如插入两个学生类型的元素,会报ClassCastException异常。本文就为大家总结了Java比较两个对象大小的三种方法,需要的可以参考一下
    2022-07-07
  • Mybatis select记录封装的实现

    Mybatis select记录封装的实现

    这篇文章主要介绍了Mybatis select记录封装的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论