• 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;
        }
    }
    

      

  • 相关阅读:
    CCoolBar 的替代方案 CDockablePane。
    CTreeView 的教程
    散列表
    Add and Search Word
    Contains Duplicate II
    Word Search II
    Implement Trie (Prefix Tree)
    (转)多进程 & 多线程的区别与适用场景
    (转)进程控制:进程的创建、终止、阻塞、唤醒和切换
    (转)几个常用的操作系统进程调度算法
  • 原文地址:https://www.cnblogs.com/sui84/p/11710751.html
Copyright © 2020-2023  润新知