利用jwt生成或解密token信息

    jwt(json web token)是一种能够允许我们在用户和服务器之间传递安全可靠信息的规范。它可以采用对称加密和非对称加密的方式,对我们所要传递的数据进行加密,防止数据的泄露。在web应用中,jwt通常可以结合Spring-security,对访问的页面进行安全保护,如果有需要,可以参照本文参考文献中的内容。本文主要对jwt的类进行封装,生成tocken信息。

    JWT 由三部分组成 头部(header)、荷载(payload) 、签名(signature)

    在使用Jwt时,我们首先在pom中引用jwt的lib

 

		
			io.jsonwebtoken
			jjwt
			0.9.0
		

    然后,我们编写一个产生tocken 和获取tocken 的java通用类,也就是对jwt中的方法进行简单的封装

public class JWT {
    
    /**
     * 利用jwt生成token信息.
     * @param claims 数据声明(Claim)其实就是一个Map,比如我们想放入用户名,
     *               可以简单的创建一个Map然后put进去
     * @param secret 用于进行签名的秘钥
     * @return
     * @throws Exception 
     */
    public static String generateToken(Map claims,String secret) throws Exception {
        DESCoder desCoder = new DESCoder();
        Key key = desCoder.toKey(secret);
//设置过期时间为10分钟
        Date ecpiration = new Date(System.currentTimeMillis()+600000L);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(ecpiration)
                .signWith(SignatureAlgorithm.HS512, key) //采用什么算法是可以自己选择的,不一定非要采用HS512
                .compact();
    }
    
    /**
     * 利用jwt解析token信息.
     * @param token 要解析的token信息
     * @param secret 用于进行签名的秘钥
     * @return
     * @throws Exception 
     */
    public static Optional getClaimsFromToken(String token,String secret) throws Exception {
        Claims claims;
        DESCoder desCoder = new DESCoder();
        Key key = desCoder.toKey(secret);
        try {
            claims = Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token)
                    .getBody();
             return Optional.of(claims);
        } catch (Exception e) {
            return Optional.empty();
        }
    }
    
    /**
     * 验证token是否过期
     * @param tooken 要解析的token信息
     * @param secret 用于进行签名的秘钥
     * @return true 表示过期,false表示不过期,如果没有设置过期时间,则也不认为过期
     * @throws Exception 
     */
    public static boolean isExpired(String tooken,String secret) throws Exception{
        Optional claims= getClaimsFromToken(tooken,secret);
        if(claims.isPresent()){
            Date expiration = claims.get().getExpiration();
             return expiration.before(new Date())
        }
        return false;
    }
    
    /**
     * 获取tooken中的参数值
     * @param tooken 要解析的token信息
     * @param secret 用于进行签名的秘钥
     * @return
     * @throws Exception 
     */
    public static Map extractInfo(String token,String secret) throws Exception{
        Optional claims = getClaimsFromToken(token,secret);
        if(claims.isPresent()){
            Map info = new HashMap();
            Set keySet = claims.get().keySet();
            //通过迭代,提取token中的参数信息
            Iterator iterator = keySet.iterator();
            while(iterator.hasNext()){
                String key = iterator.next();
                Object value =  claims.get().get(key);
                info.put(key,value);
                
            }
            return info;
        }
        return null;
    }
   
}

    上述方法中的generateToken(Map claims,String secret)为产生token的方法,claims中为包含发送内容的map数据,方法中的SignatureAlgorithm.HS512 为加密算法,为对称加密,如果想使用非对称加密方法,需要改为RS256,同时,传入的key必须是公私钥,具体可参照“RS256加密JWT生成、验证”。signWith(SignatureAlgorithm.HS512, key)方法中的“key”可以为String类型,也可以为Key类型,如果我们在方法中传入keyd的类型为String时,signWith会自动将其转化为Key类型。上面方法中,我们直接传入String类型的secret为使用base64编码DES加密的String,大家如果觉得麻烦,可以直接输入String生成token,以及使用相同的string解密token信息,不需要看以下内容。

    上面中我们使用到的DESCoder类的内容为:

 

private  Key toKey(byte[] key) throws Exception {
		DESKeySpec dks = new DESKeySpec(key);
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORTHM);
		SecretKey secretKey = keyFactory.generateSecret(dks);
		return secretKey;
	}
	
	/**
	 * 
	 * @param key key(Base64编码)
	 * @return
	 * @throws Exception
	 */
	public Key toKey(String key) throws Exception{
	    byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
	    Key keyObj = toKey(keyBytes);
        return keyObj;
	}

 

    DES加密算法的生成方法为

 

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.SecureRandom;
import java.util.Map;

import javax.crypto.KeyGenerator;

import sun.misc.BASE64Encoder;

public class DESBuilder {

	/** 加密算法 */
	public static final String KEY_ALGORTHM = "DES";

	private Key key;

	/**
	 * 构造函数.
	 * 
	 * @param str
	 *            传入的字符串,根据字符串随机生成Key
	 */
	public DESBuilder(String str) {
		generatorRandomKey(str);
	}

	/**
	 * @param strKey
	 *            通过strKey生成随机Key
	 */
	public void generatorRandomKey(String strKey) {
		try {
			KeyGenerator generator = KeyGenerator.getInstance(KEY_ALGORTHM);
			generator.init(new SecureRandom(strKey.getBytes()));
			this.key = generator.generateKey();
			generator = null;
		} catch (Exception e) {
			throw new RuntimeException("Error initializing SqlMap class. Cause: " + e);
		}
	}

	/**
	 * @param strKey
	 *            通过strKey生成Key
	 * 
	 * @return Key对象
	 */
	public Key getKey() {
		return key;
	}

	/**
	 * @param strKey
	 *            通过strKey生成Key
	 * 
	 * @return Key对象
	 */
	public String getKeyToString() {
		return (new BASE64Encoder()).encodeBuffer(key.getEncoded());
	}

	/**
	 * @param filePath
	 *            秘钥的存储路径(建议秘钥使用“.bat”后缀)
	 * 
	 * @return 文件
	 */
	public void getKeyToFile(String keyAddress) {
		FileOutputStream fileOutput = null;
		ObjectOutputStream objectOutput = null;
		try {
			fileOutput = new FileOutputStream(keyAddress);
			objectOutput = new ObjectOutputStream(fileOutput);
			objectOutput.writeObject(this.key);
			System.out.println("success: " + keyAddress);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fileOutput.close();
				objectOutput.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
    至此,已经介绍完成jwt生成和解析token信息的方法,里面涉及到如何进行base64编码解码,如何生成用DES加解密以及Key类型数据的产生。

 

 

参考文献

 

1、JSON Web Token - 在Web应用间安全地传递信息

2、RS256加密JWT生成、验证

3、使用JWT保护你的Spring Boot应用 - Spring Security实战

4、使用JWT和Spring Security保护REST API

 

你可能感兴趣的:(java)