JWT Token的生成和解析及MD5加/解密
jwt Token生成工具类, 及MD5加密解密工具类
- 生成的工具类, 网上很多; 我记录下我用的, 代码如下:
JwtToken类
package com.common;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
/**
* APP登录Token的生成和解析
*/
public class JwtToken {
/** token秘钥,请勿泄露,请勿随便修改 backups:SECRETKey */
public static final String SECRET = "SECRETKey"; //这里是我随便填的, 用的时候要修改
/** token 过期时间: 10天 */
public static final int CALENDARFIELD = Calendar.DATE;
public static final int CALENDARINTERVAL = 10;
/**
* JWT生成Token.<br/>
* JWT构成: header, payload, signature
* @param user_id
* 登录成功后用户user_id, 参数user_id不可传空
*/
public static String createToken(String userJson) throws Exception {
userJson = AesEncryption.encrypt(userJson);
Date iatDate = new Date();
// expire time
Calendar nowTime = Calendar.getInstance();
nowTime.add(CALENDARFIELD, CALENDARINTERVAL);
Date expiresDate = nowTime.getTime();
// header Map
Map<String, Object> map = new HashMap<String, Object>();
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = JWT.create().withHeader(map) // heade
.withClaim("iss", "Service") // payload
.withClaim("aud", "APP").withClaim("user", null == userJson ? null : userJson)
.withIssuedAt(iatDate) // sign time
.withExpiresAt(expiresDate) // expire time
.sign(Algorithm.HMAC256(SECRET)); // signature
return token;
}
/**
* 解密Token
* @param token
* @return
* @throws Exception
*/
public static Map<String, Claim> verifyToken(String token) {
DecodedJWT jwt = null;
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
jwt = verifier.verify(token);
} catch (Exception e) {
e.printStackTrace();// token 校验失败, 抛出Token验证非法异常
}
return jwt.getClaims();
}
/**
* 根据Token获取user
* @param token
* @return user
* @throws Exception
*/
public static String getUser(String token) throws Exception {
Map<String, Claim> claims = verifyToken(token);
Claim userClaim = claims.get("user");
if (null == userClaim || StringUtils.isEmpty(userClaim.asString())) {
new Exception("token 校验失败, Token验证非法异常");
// token 校验失败, 抛出Token验证非法异常
}
return AesEncryption.desencrypt(userClaim.asString());
}
}
AES加密,解密
package com.common;
import com.util.MD5Utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesEncryption {
private static final String KEY = "aaaa123456"; // 用的时候要修改
private static final String IV = "aaaa123456"; // 用的时候要修改
/**
* 加密
* @param data
* @return
* @throws Exception
*/
public static String encrypt(String data) throws Exception {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = data.getBytes("UTF-8");
int plaintextLength = dataBytes.length;
if ((plaintextLength == 96) || (plaintextLength % blockSize != 0)) {// 96刚好加密大于128位
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
SecretKeySpec keyspec = new SecretKeySpec(KEY.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
return Base64Method.encryptBase64(encrypted);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 解密
* @param data
* @return
* @throws Exception
*/
public static String desencrypt(String data) {
try {
byte[] encrypted1 = Base64Method.decryptBase64ForByte(data);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(KEY.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] rawOriginal = cipher.doFinal(encrypted1);
byte[] original = new String(rawOriginal).replaceAll("\0", "").getBytes();
String originalString = new String(original, "UTF-8");
return originalString;
} catch (Exception e) {
System.out.println("密码解密异常===================");
return null;
}
}
//需要的时候用主方法, 看自己的密码加解密后是什么
public static void main(String[] args) throws Exception {
// String pwd = "password";
// String str = AesEncryption.encrypt(pwd);
// System.out.println("加密后:" + str);
// System.out.println("解密后:" + AesEncryption.desencrypt(str));
// System.out.println("MD5加密后:" + MD5Utils.generate(pwd));
}
}
Base64Method类
package com.common;
import java.io.IOException;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class Base64Method {
public static String encryptBase64(String strString) throws Exception {
Base64 base64 = new Base64();
String base64str = new String(base64.encode(strString.getBytes("utf-8")), "utf-8");
base64str = base64str.replace("\n", "").replace("\r", "").replace('+', '-').replace('/', '_');
return base64str;
}
public static String encryptBase64(byte[] bytes) throws Exception {
Base64 base64 = new Base64();
String base64str = new String(base64.encode(bytes), "utf-8");
base64str = base64str.replace("\n", "").replace("\r", "").replace('+', '-').replace('/', '_');
return base64str;
}
public static String decryptBase64(String strString) throws Exception {
Base64 base64 = new Base64();
byte[] bytes = base64.decode(strString.replace('-', '+').replace('_', '/').getBytes("utf-8"));
String str = new String(bytes, "utf-8");
return str;
}
public static byte[] decryptBase64ForByte(String strString) throws Exception {
Base64 base64 = new Base64();
byte[] bytes = base64.decode(strString.replace('-', '+').replace('_', '/').getBytes("utf-8"));
return bytes;
}
public static byte[] safeUrlBase64Decode(final String safeBase64Str) throws IOException {
String base64Str = safeBase64Str.replace('-', '+');
base64Str = base64Str.replace('_', '/');
int mod4 = base64Str.length() % 4;
if (mod4 > 0) {
base64Str = base64Str + "====".substring(mod4);
}
return new BASE64Decoder().decodeBuffer(base64Str);
}
public static String safeUrlBase64Encode(byte[] data) {
String encodeBase64 = new BASE64Encoder().encode(data);
String safeBase64Str = encodeBase64.replace('+', '-');
safeBase64Str = safeBase64Str.replace('/', '_');
safeBase64Str = safeBase64Str.replaceAll("=", "");
return safeBase64Str;
}
}
3. 上面代码使用了Cipher类实现加密
可以看我转载的一个文章, 链接: https://blog.csdn.net/weixin_45305706/article/details/106378476.
MD5Utils工具类
package com.util;
import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
import java.util.Random;
public class MD5Utils {
private static final String[] hexDigIts = {"s","e","c","r","e","t","k","e","y","1","2","3","4","5","6","7"}; // 用的时候要修改, 长短也不是固定的, 随意改
/**
* 生成含有随机盐的密码
*/
public static String generate(String password) {
Random r = new Random();
StringBuilder sb = new StringBuilder(16);
sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));
int len = sb.length();
if (len < 16) {
for (int i = 0; i < 16 - len; i++) {
sb.append("0");
}
}
String salt = sb.toString();
password = md5Hex(password + salt);
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = password.charAt(i / 3 * 2);
char c = salt.charAt(i / 3);
cs[i + 1] = c;
cs[i + 2] = password.charAt(i / 3 * 2 + 1);
}
return new String(cs);
}
/**
* 校验密码是否正确
*/
public static boolean verify(String password, String md5) {
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = md5.charAt(i);
cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);
cs2[i / 3] = md5.charAt(i + 1);
}
String salt = new String(cs2);
return md5Hex(password + salt).equals(new String(cs1));
}
/**
* 获取十六进制字符串形式的MD5摘要
*/
public static String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(src.getBytes());
return new String(new Hex().encode(bs));
} catch (Exception e) {
return null;
}
}
/**
* MD5加密
* @param origin 字符
* @param charsetname 编码
* @return
*/
public static String MD5Encode(String origin, String charsetname){
String resultString = null;
try{
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if(null == charsetname || "".equals(charsetname)){
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
}else{
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
}
}catch (Exception e){
}
return resultString;
}
public static String byteArrayToHexString(byte b[]){
StringBuffer resultSb = new StringBuffer();
for(int i = 0; i < b.length; i++){
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
public static String byteToHexString(byte b){
int n = b;
if(n < 0){
n += 256;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigIts[d1] + hexDigIts[d2];
}
//需要的时候, 可以用主方法测试一下
/*
* public static void main(String[] args) {
* System.out.println(generate("abcd@zand")); // 用的时候要修改
* //BigDecimal as = new BigDecimal("0");
* //String md = generate("110.01"); // 用的时候要修改
* //System.out.println(md);
* //System.out.println(verify("110.01",md));
* //System.out.println(generate(as.toString())); }
*/
}
- 以上的代码, 稍稍修改就能用;
- 有兴趣的, 请提出问题, 一起交流;
- 下一篇记录zuul网关的使用;