All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
cn.k7g.alloy.expose.AlloyContentHandler Maven / Gradle / Ivy
package cn.k7g.alloy.expose;
import cn.k7g.alloy.exception.AlloyContentDecodeException;
import cn.k7g.alloy.exception.AlloyContentEncodeException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* 加密的内容的处理器,根据key生成内容
*
* @author victor-wu
* @date 2024年4月3日
*/
public abstract class AlloyContentHandler {
public static final Class[] BASIC_TYPE = {
Long.class,
String.class,
Integer.class,
long.class,
int.class,
Boolean.class,
boolean.class,
Byte.class,
byte.class,
Double.class,
double.class,
Float.class,
float.class,
Short.class,
short.class,};
@Autowired
private ObjectMapper objectMapper;
/**
* 返回一个匿名情况下的 key,这个通常是固定的一个值,
* 在没有登录的情况下用户都将使用这个key
*
* @return
*/
public abstract byte[] anonymousOwnerKey();
/**
* 数据拥有者,一般为用户ID 或者 租户ID 商户ID等,不可超出32长度
*
* @return
*/
public abstract byte[] ownerKey();
/**
* 是否登录,如果已经登录就用 ownerKey 否则就是 anonymousOwnerKey
*
* @return
*/
public abstract boolean isLogin();
public byte[] getKey() {
return getKey(false);
}
/**
* 填充KEY,超出范围截断
*
* @param forceAny 强制使用匿名key, 不论是否登录都使用匿名key。
* @return 返回用于加密的key
*/
public byte[] getKey(boolean forceAny) {
byte[] key = !forceAny && isLogin() ? ownerKey() : anonymousOwnerKey();
if (key.length > 32) {
throw new RuntimeException("alloy key 长度不能超过32");
}
if (key.length == 16 || key.length == 24 || key.length == 32) {
return key;
}
if (key.length < 16) {
return fill(key, 16);
}
if (key.length < 24) {
return fill(key, 24);
}
return fill(key, 32);
}
public byte[] fill(byte[] key, int len) {
byte[] nk = new byte[len];
System.arraycopy(key, 0, nk, 0, key.length);
for (int i = key.length; i < nk.length; i++) {
nk[i] = '0';
}
return nk;
}
/**
* 解密, 返回解码后的明文
*
* @param value 密文
* @param key 必须是一个AES有效的内容,不做二次处理
* @return 返回一个解密后的内容
*/
public static String decode(String value, byte[] key) {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
// 创建AES加密器
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 解密文本
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(Base64.getUrlDecoder().decode(value));
return new String(decryptedBytes, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new AlloyContentDecodeException("无效的alloy content", e);
}
}
/**
* 加密, 返回加密后的内容
*
* @param originId 原始数据ID
* @param key 必须是一个AES有效的内容,不做二次处理
* @return 返回一个加密后的内容
*/
public static String encode(String originId, byte[] key) {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
// 创建AES加密器
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 加密文本
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedBytes = cipher.doFinal(originId.getBytes(StandardCharsets.UTF_8));
return Base64.getUrlEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
throw new AlloyContentEncodeException("加密失败", e);
}
}
/**
* 将AlloyContent转化成对象
*
* @param content 密文
* @param dataType 转化类型
* @return 解密后的对象
* @throws JsonProcessingException json解析错误
*/
public T decodeObject(String content, Class dataType) throws JsonProcessingException {
String originContent;
try {
originContent = decode(content, getKey());
} catch (Exception e) {
// 这里是解密操作,出现的异常只可能是解密失败。
// 在未登录的情况下访问的数据,登录后再次访问会导致解码结果不一致。
originContent = decode(content, getKey(true));
}
return objectMapper.readValue(originContent, dataType);
}
// public Object decodeObject(String content, Class dataType) throws JsonProcessingException {
// String originContent = decode(content, getKey());
// if (dataType.isAssignableFrom(Long.class)) {
// return Long.parseLong(originContent);
// } else if (dataType.isAssignableFrom(String.class)) {
// return originContent;
// } else if (dataType.isAssignableFrom(Integer.class)) {
// return Integer.parseInt(originContent);
// } else if (dataType.isAssignableFrom(long.class)) {
// return Long.parseLong(originContent);
// } else if (dataType.isAssignableFrom(int.class)) {
// return Integer.parseInt(originContent);
// } else if (dataType.isAssignableFrom(Boolean.class)) {
// return Boolean.parseBoolean(originContent);
// } else if (dataType.isAssignableFrom(boolean.class)) {
// return Boolean.parseBoolean(originContent);
// } else if (dataType.isAssignableFrom(Byte.class)) {
// return Byte.parseByte(originContent);
// } else if (dataType.isAssignableFrom(byte.class)) {
// return Byte.parseByte(originContent);
// } else if (dataType.isAssignableFrom(Double.class)) {
// return Double.parseDouble(originContent);
// } else if (dataType.isAssignableFrom(double.class)) {
// return Double.parseDouble(originContent);
// } else if (dataType.isAssignableFrom(Float.class)) {
// return Float.parseFloat(originContent);
// } else if (dataType.isAssignableFrom(float.class)) {
// return Float.parseFloat(originContent);
// } else if (dataType.isAssignableFrom(Short.class)) {
// return Short.parseShort(originContent);
// } else if (dataType.isAssignableFrom(short.class)) {
// return Short.parseShort(originContent);
// } else {
// return objectMapper.readValue(originContent, dataType);
// }
// }
/**
* 将对象值转化为 AlloyContent
*
* @param o
* @return
* @throws JsonProcessingException
*/
public String encodeObject(Object o) throws JsonProcessingException {
// for (Class cls : BASIC_TYPE) {
// if (o.getClass().isAssignableFrom(cls)) {
// return encode(o.toString(), getKey());
// }
// }
return encode(objectMapper.writeValueAsString(o), getKey());
}
}