Java验证jwt token

https://jwt.io/

RS256加密JWT生成、验证

https://blog.csdn.net/u011411069/article/details/79966226

How to load public certificate from pem file..?

https://www.howtobuildsoftware.com/index.php/how-do/ciLJ/java-ssl-cryptography-bouncycastle-public-key-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;
    }
}

  

 

posted on 2019-10-20 22:58  白马酒凉  阅读(3413)  评论(0编辑  收藏  举报

导航