package com.ty.qdd.utils;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ty.qdd.pojo.po.app.UserInfoPO;
import com.ty.qdd.pojo.vo.app.userInfo.TokenVo;
import lombok.SneakyThrows;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.lang.NonNull;
import org.springframework.util.DigestUtils;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;
public class TokenUtils {
public final static String tokenHeader = "QDD-USER-TOKEN";
// Base64 编码
private static final Base64 base64 = new Base64();
// AES加密算法
private static final String AES_ALGORITHM = "AES";
// AES加密算法秘钥
private static final String aesSecretKey = "W7MBMBnSi2s9v5rHCXRh7c+ZDydR98atPnqVdQA+zlfUCQ==";
/**
* AES加密
* @param content 需要加密的明文
* @return 加密后的密文(str/key为null返回null)
*/
public static String aesEncode(@NonNull String content) {
return aesEncode(content,false);
}
/**
* AES加密
* @param content 需要加密的明文
* @param urlSafety 密文是否需要Url安全
* @return 加密后的密文(str/key为null返回null)
*/
public static String aesEncode(@NonNull String content, boolean urlSafety) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
keyGenerator.init(128, new SecureRandom(aesSecretKey.getBytes()));
SecretKey secretKey = keyGenerator.generateKey();
SecretKeySpec key = new SecretKeySpec(secretKey.getEncoded(), AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] bytes = cipher.doFinal(byteContent);
if (urlSafety) {
return Base64.encodeBase64URLSafeString(bytes);
}
else {
return new String(base64.encode(bytes));
}
}
catch (Exception e) {
System.err.println("AES加密失败, 明文:" + content + ", key:" + aesSecretKey + ", 错误:" + e.getMessage());
}
return null;
}
/**
* AES解密
* @param content 需要解密的密文(base64编码字符串)
* @return 解密后的明文
*/
public static String aesDecode(@NonNull String content) {
return aesDecode(content,false);
}
/**
* AES解密
* @param content 需要解密的密文(base64编码字符串)
* @param urlSafety 密文是否有Url安全
* @return 解密后的明文
*/
public static String aesDecode(@NonNull String content, boolean urlSafety) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
keyGenerator.init(128, new SecureRandom(aesSecretKey.getBytes()));
SecretKey secretKey = keyGenerator.generateKey();
SecretKeySpec key = new SecretKeySpec(secretKey.getEncoded(), AES_ALGORITHM);
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
// 解密
if (urlSafety){
content = new String(cipher.doFinal(Base64.decodeBase64URLSafe(content)), StandardCharsets.UTF_8);
}else {
content = new String(cipher.doFinal(base64.decode(content)), StandardCharsets.UTF_8);
}
return content;
} catch (Exception e) {
System.err.println("AES解密失败, 密文:" + content + ", key:" + aesSecretKey + ", 错误:" + e.getMessage());
}
return null;
}
/**
* 生成token
* @param userInfoPO 用户信息
* @param expire token时长
* @param timeUnit 时间类型
* @return 返回生成的token
*/
@SneakyThrows
public static synchronized String createToken(@NonNull UserInfoPO userInfoPO, @NonNull Integer expire, @NonNull TimeUnit timeUnit) {
//开始时间
long begin = System.currentTimeMillis();
//过期时间
long end = 0;
switch (timeUnit){
case SECONDS: {
end = begin + expire * 1000;
break;
}
case MINUTES: {
end = begin + expire * 60 * 1000;
break;
}
case HOURS: {
end = begin + expire * 60 * 60 * 1000;
break;
}
case DAYS: {
end = begin + expire * 24 * 60 * 60 * 1000;
break;
}
default: {
end = begin + expire;
break;
}
}
//写入 TokenVo
TokenVo tokenVo = new TokenVo(userInfoPO.getId(),userInfoPO.getUsername(),begin,end);
//将实体类转化
String token = new ObjectMapper().writeValueAsString(tokenVo);
//return new String(base64.encode(token.getBytes()));
//AES加密返回
return aesEncode(token,true);
}
/**
* 对 token 进行解密,转化成 TokenVo
* @param token
* @return
*/
public static synchronized TokenVo decodeToken(String token){
return JSONObject.parseObject(aesDecode(token,true),TokenVo.class);
}
/**
* 验证token是否存在或过期
* @param token 值
* @return 返回值
*/
public static boolean validateToken_2(String token){
if (!RedisUtils.exist(RedisUtils.LOGIN_USER_KEY + token)){
return false;
}
return getEndTimeFromToken(token) >= System.currentTimeMillis();
}
/**
* 通过 token 获取用户id
* @param token 传入token
* @return 返回用户名
*/
public static Long getUserIdFromToken(String token){
return decodeToken(token).getUserId();
}
/**
* 通过 token 获取用户名
* @param token 传入token
* @return 返回用户名
*/
public static String getUsernameFromToken(String token){
return decodeToken(token).getUsername();
}
/**
* 通过 token 获取 token起始时间
* @param token 传入token
* @return 返回token起始时间
*/
public static Long getBeginTimeFromToken(String token){
return decodeToken(token).getBegin();
}
/**
* 通过 token 获取 token过期时间
* @param token 传入token
* @return 返回token过期时间
*/
public static Long getEndTimeFromToken(String token){
return decodeToken(token).getEnd();
}
}
AES加密算法 生成token
最新推荐文章于 2024-02-02 17:01:18 发布
这是一个Java工具类,实现了AES加密和解密,并用于生成包含用户信息的Token。加密过程使用了Base64编码和AES算法,解密同样基于AES。Token的生成结合了用户信息、过期时间和AES加密,提供了验证Token有效性和从Token中获取用户信息的方法。
摘要由CSDN通过智能技术生成