mirror of
				https://gitee.com/dromara/hutool.git
				synced 2025-10-31 16:36:56 +08:00 
			
		
		
		
	add hutool-jwt
This commit is contained in:
		| @@ -15,6 +15,7 @@ import java.io.File; | ||||
| import java.io.InputStream; | ||||
| import java.io.Serializable; | ||||
| import java.security.Key; | ||||
| import java.security.MessageDigest; | ||||
|  | ||||
| /** | ||||
|  * HMAC摘要算法<br> | ||||
| @@ -28,9 +29,9 @@ import java.security.Key; | ||||
|  */ | ||||
| public class HMac implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
| 	 | ||||
|  | ||||
| 	private final MacEngine engine; | ||||
| 	 | ||||
|  | ||||
| 	// ------------------------------------------------------------------------------------------- Constructor start | ||||
| 	/** | ||||
| 	 * 构造,自动生成密钥 | ||||
| @@ -39,7 +40,7 @@ public class HMac implements Serializable { | ||||
| 	public HMac(HmacAlgorithm algorithm) { | ||||
| 		this(algorithm, (Key)null); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 * @param algorithm 算法 {@link HmacAlgorithm} | ||||
| @@ -48,7 +49,7 @@ public class HMac implements Serializable { | ||||
| 	public HMac(HmacAlgorithm algorithm, byte[] key) { | ||||
| 		this(algorithm.getValue(), key); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 * @param algorithm 算法 {@link HmacAlgorithm} | ||||
| @@ -57,7 +58,7 @@ public class HMac implements Serializable { | ||||
| 	public HMac(HmacAlgorithm algorithm, Key key) { | ||||
| 		this(algorithm.getValue(), key); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 * @param algorithm 算法 | ||||
| @@ -67,7 +68,7 @@ public class HMac implements Serializable { | ||||
| 	public HMac(String algorithm, byte[] key) { | ||||
| 		this(algorithm, new SecretKeySpec(key, algorithm)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 * @param algorithm 算法 | ||||
| @@ -77,7 +78,7 @@ public class HMac implements Serializable { | ||||
| 	public HMac(String algorithm, Key key) { | ||||
| 		this(MacEngineFactory.createEngine(algorithm, key)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 * @param engine MAC算法实现引擎 | ||||
| @@ -87,11 +88,11 @@ public class HMac implements Serializable { | ||||
| 		this.engine = engine; | ||||
| 	} | ||||
| 	// ------------------------------------------------------------------------------------------- Constructor end | ||||
| 	 | ||||
|  | ||||
| 	// ------------------------------------------------------------------------------------------- Digest | ||||
| 	/** | ||||
| 	 * 生成文件摘要 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @param charset 编码 | ||||
| 	 * @return 摘要 | ||||
| @@ -99,20 +100,20 @@ public class HMac implements Serializable { | ||||
| 	public byte[] digest(String data, String charset) { | ||||
| 		return digest(StrUtil.bytes(data, charset)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成文件摘要 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @return 摘要 | ||||
| 	 */ | ||||
| 	public byte[] digest(String data) { | ||||
| 		return digest(data, CharsetUtil.UTF_8); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成文件摘要,并转为16进制字符串 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @param charset 编码 | ||||
| 	 * @return 摘要 | ||||
| @@ -120,21 +121,21 @@ public class HMac implements Serializable { | ||||
| 	public String digestHex(String data, String charset) { | ||||
| 		return HexUtil.encodeHexStr(digest(data, charset)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成文件摘要 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @return 摘要 | ||||
| 	 */ | ||||
| 	public String digestHex(String data) { | ||||
| 		return digestHex(data, CharsetUtil.UTF_8); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成文件摘要<br> | ||||
| 	 * 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param file 被摘要文件 | ||||
| 	 * @return 摘要bytes | ||||
| 	 * @throws CryptoException Cause by IOException | ||||
| @@ -148,52 +149,52 @@ public class HMac implements Serializable { | ||||
| 			IoUtil.close(in); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成文件摘要,并转为16进制字符串<br> | ||||
| 	 * 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param file 被摘要文件 | ||||
| 	 * @return 摘要 | ||||
| 	 */ | ||||
| 	public String digestHex(File file) { | ||||
| 		return HexUtil.encodeHexStr(digest(file)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 数据bytes | ||||
| 	 * @return 摘要bytes | ||||
| 	 */ | ||||
| 	public byte[] digest(byte[] data) { | ||||
| 		return digest(new ByteArrayInputStream(data), -1); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要,并转为16进制字符串<br> | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @return 摘要 | ||||
| 	 */ | ||||
| 	public String digestHex(byte[] data) { | ||||
| 		return HexUtil.encodeHexStr(digest(data)); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要,使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data {@link InputStream} 数据流 | ||||
| 	 * @return 摘要bytes | ||||
| 	 */ | ||||
| 	public byte[] digest(InputStream data) { | ||||
| 		return digest(data, IoUtil.DEFAULT_BUFFER_SIZE); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要,并转为16进制字符串<br> | ||||
| 	 * 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @return 摘要 | ||||
| 	 */ | ||||
| @@ -203,7 +204,7 @@ public class HMac implements Serializable { | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要 | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data {@link InputStream} 数据流 | ||||
| 	 * @param bufferLength 缓存长度,不足1使用 {@link IoUtil#DEFAULT_BUFFER_SIZE} 做为默认值 | ||||
| 	 * @return 摘要bytes | ||||
| @@ -211,11 +212,11 @@ public class HMac implements Serializable { | ||||
| 	public byte[] digest(InputStream data, int bufferLength) { | ||||
| 		return this.engine.digest(data, bufferLength); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * 生成摘要,并转为16进制字符串<br> | ||||
| 	 * 使用默认缓存大小,见 {@link IoUtil#DEFAULT_BUFFER_SIZE} | ||||
| 	 *  | ||||
| 	 * | ||||
| 	 * @param data 被摘要数据 | ||||
| 	 * @param bufferLength 缓存长度,不足1使用 {@link IoUtil#DEFAULT_BUFFER_SIZE} 做为默认值 | ||||
| 	 * @return 摘要 | ||||
| @@ -224,6 +225,20 @@ public class HMac implements Serializable { | ||||
| 		return HexUtil.encodeHexStr(digest(data, bufferLength)); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 验证生成的摘要与给定的摘要比较是否一致<br> | ||||
| 	 * 简单比较每个byte位是否相同 | ||||
| 	 * | ||||
| 	 * @param digest 生成的摘要 | ||||
| 	 * @param digestToCompare 需要比较的摘要 | ||||
| 	 * @return 是否一致 | ||||
| 	 * @since 5.6.8 | ||||
| 	 * @see MessageDigest#isEqual(byte[], byte[]) | ||||
| 	 */ | ||||
| 	public boolean verify(byte[] digest, byte[] digestToCompare){ | ||||
| 		return MessageDigest.isEqual(digest, digestToCompare); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 获取MAC算法块长度 | ||||
| 	 * @return MAC算法块长度 | ||||
|   | ||||
| @@ -1,11 +1,9 @@ | ||||
| package cn.hutool.json.jwt; | ||||
|  | ||||
| import cn.hutool.core.lang.Assert; | ||||
| import cn.hutool.json.JSONUtil; | ||||
| import cn.hutool.json.JSONObject; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * Claims 认证 | ||||
| @@ -15,14 +13,14 @@ import java.util.Map; | ||||
| public class Claims implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private final Map<String, Object> claimMap; | ||||
| 	private final JSONObject claimJSON; | ||||
|  | ||||
| 	public Claims() { | ||||
| 		this.claimMap = new HashMap<>(); | ||||
| 		this.claimJSON = new JSONObject(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 增加Claims属性 | ||||
| 	 * 增加Claims属性,如果属性值为{@code null},则移除这个属性 | ||||
| 	 * | ||||
| 	 * @param name  属性名 | ||||
| 	 * @param value 属性值 | ||||
| @@ -30,19 +28,10 @@ public class Claims implements Serializable { | ||||
| 	protected void setClaim(String name, Object value) { | ||||
| 		Assert.notNull(name, "Name must be not null!"); | ||||
| 		if (value == null) { | ||||
| 			claimMap.remove(name); | ||||
| 			claimJSON.remove(name); | ||||
| 			return; | ||||
| 		} | ||||
| 		claimMap.put(name, value); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 获取Claims数据Map | ||||
| 	 * | ||||
| 	 * @return map | ||||
| 	 */ | ||||
| 	protected Map<String, Object> getClaimMap() { | ||||
| 		return this.claimMap; | ||||
| 		claimJSON.set(name, value); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -51,6 +40,6 @@ public class Claims implements Serializable { | ||||
| 	 * @return JSON字符串 | ||||
| 	 */ | ||||
| 	public String getClaimsJson() { | ||||
| 		return JSONUtil.toJsonStr(getClaimMap()); | ||||
| 		return this.claimJSON.toString(); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,15 @@ | ||||
| package cn.hutool.json.jwt; | ||||
|  | ||||
| import cn.hutool.core.codec.Base64; | ||||
| import cn.hutool.core.util.CharsetUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.hutool.json.jwt.signers.JWTSigner; | ||||
|  | ||||
| import java.nio.charset.Charset; | ||||
|  | ||||
| /** | ||||
|  * JSON Web Token (JWT),基于JSON的开放标准((RFC 7519)用于在网络应用环境间传递声明。<br> | ||||
|  * | ||||
|  * <p> | ||||
|  * 结构:xxxxx.yyyyy.zzzzz | ||||
|  * <ul> | ||||
|  *     <li>header:主要声明了JWT的签名算法</li> | ||||
| @@ -23,14 +25,41 @@ import java.nio.charset.Charset; | ||||
|  */ | ||||
| public class JWT { | ||||
|  | ||||
| 	private Charset charset; | ||||
| 	private Signer signer; | ||||
| 	private final JWTHeader header; | ||||
| 	private final JWTPayload payload; | ||||
|  | ||||
| 	private Charset charset; | ||||
| 	private JWTSigner signer; | ||||
|  | ||||
| 	/** | ||||
| 	 * 构造 | ||||
| 	 */ | ||||
| 	public JWT() { | ||||
| 		this.header = new JWTHeader(); | ||||
| 		this.payload = new JWTPayload(); | ||||
| 		this.charset = CharsetUtil.CHARSET_UTF_8; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 设置编码 | ||||
| 	 * | ||||
| 	 * @param charset 编码 | ||||
| 	 * @return this | ||||
| 	 */ | ||||
| 	public JWT setCharset(Charset charset) { | ||||
| 		this.charset = charset; | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * 设置签名算法 | ||||
| 	 * | ||||
| 	 * @param signer 签名算法 | ||||
| 	 * @return this | ||||
| 	 */ | ||||
| 	public JWT setSigner(JWTSigner signer) { | ||||
| 		this.signer = signer; | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| @@ -38,7 +67,7 @@ public class JWT { | ||||
| 	 * | ||||
| 	 * @return JWT字符串 | ||||
| 	 */ | ||||
| 	public String sign(){ | ||||
| 	public String sign() { | ||||
| 		final String headerBase64 = Base64.encodeUrlSafe(this.header.getClaimsJson(), charset); | ||||
| 		final String payloadBase64 = Base64.encodeUrlSafe(this.payload.getClaimsJson(), charset); | ||||
| 		final String sign = signer.sign(headerBase64, payloadBase64); | ||||
|   | ||||
| @@ -34,7 +34,7 @@ public class JWTHeader extends Claims { | ||||
| 	 * @param keyId kid | ||||
| 	 * @return this | ||||
| 	 */ | ||||
| 	public JWTHeader addKeyId(String keyId) { | ||||
| 	public JWTHeader setKeyId(String keyId) { | ||||
| 		setClaim(KEY_ID, keyId); | ||||
| 		return this; | ||||
| 	} | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| package cn.hutool.json.jwt; | ||||
|  | ||||
| public interface Signer { | ||||
|  | ||||
| 	String sign(String header, String payload); | ||||
| } | ||||
| @@ -0,0 +1,17 @@ | ||||
| package cn.hutool.json.jwt.signers; | ||||
|  | ||||
| /** | ||||
|  * JWT签名接口封装,通过实现此接口,完成不同算法的签名功能 | ||||
|  * | ||||
|  * @author looly | ||||
|  */ | ||||
| public interface JWTSigner { | ||||
|  | ||||
| 	/** | ||||
| 	 * 签名 | ||||
| 	 * @param header JWT头的JSON字符串 | ||||
| 	 * @param payload JWT载荷的JSON字符串 | ||||
| 	 * @return 签名结果,即JWT的第三部分 | ||||
| 	 */ | ||||
| 	String sign(String header, String payload); | ||||
| } | ||||
							
								
								
									
										29
									
								
								hutool-jwt/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								hutool-jwt/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?xml version='1.0' encoding='utf-8'?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||||
| 	<modelVersion>4.0.0</modelVersion> | ||||
|  | ||||
| 	<packaging>jar</packaging> | ||||
|  | ||||
| 	<parent> | ||||
| 		<groupId>cn.hutool</groupId> | ||||
| 		<artifactId>hutool-parent</artifactId> | ||||
| 		<version>5.6.8-SNAPSHOT</version> | ||||
| 	</parent> | ||||
|  | ||||
| 	<artifactId>hutool-jwt</artifactId> | ||||
| 	<name>${project.artifactId}</name> | ||||
| 	<description>Hutool JWT生成、解析和验证实现</description> | ||||
|  | ||||
| 	<dependencies> | ||||
| 		<dependency> | ||||
| 			<groupId>cn.hutool</groupId> | ||||
| 			<artifactId>hutool-json</artifactId> | ||||
| 			<version>${project.parent.version}</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>cn.hutool</groupId> | ||||
| 			<artifactId>hutool-crypto</artifactId> | ||||
| 			<version>${project.parent.version}</version> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
| </project> | ||||
		Reference in New Issue
	
	Block a user
	 Looly
					Looly