Files
nuttyreading-java/src/main/java/com/peanut/common/utils/PlayToken.java
2024-07-19 13:53:35 +08:00

209 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.peanut.common.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.peanut.modules.common.dao.VodAesTokenDao;
import com.peanut.modules.common.entity.VodAesTokenEntity;
import lombok.Data;
import java.util.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
import java.util.List;
@Component
public class PlayToken {
@Autowired
private VodAesTokenDao vodAesTokenDao;
//非AES生成方式无需以下参数
private static String ENCRYPT_KEY = "abcdefgh#$&!mnopqrstuvwxyz123456"; //加密Key为用户自定义的字符串长度为16、24或32位
private static String INIT_VECTOR = "ABCDEFGHIJKLMNOP"; //加密偏移量为用户自定义字符串长度为16位不能含有特殊字符
// public static void main(String[] args) throws Exception {
//
// String serviceId = "12";
// PlayToken playToken = new PlayToken();
// String aesToken = playToken.generateToken(serviceId);
// //System.out.println("aesToken " + aesToken);
// //System.out.println(playToken.validateToken(aesToken)); //验证解密部分
//
// }
/**
* 根据传递的参数生成令牌
* 说明:
* 1、参数可以是业务方的用户ID、播放终端类型等信息
* 2、调用令牌接口时生成令牌Token
* @return
*/
public String generateToken() throws Exception {
// if (null == args || args.length <= 0) {
// return null;
// }
// String base = StringUtils.join(Arrays.asList(args), "_");
int bas = (int)(Math.random()*90+10);
String base = String.valueOf(bas);
//设置60S后该token过期过期时间可以自行调整
long expire = System.currentTimeMillis() + 60000L;
base += "_" + expire; //自定义字符串base的长度为16位字符此例中时间戳占13位下划线_占1位则还需传入2位字符。实际配置时也可按需全部更改最终保证base为16、24或32位字符串即可。
//生成token
String token = encrypt(base); //arg1为要加密的自定义字符串arg2为加密Key
//保存token用于解密时校验token的有效性例如过期时间、token的使用次数
saveToken(token);
return token;
}
/**
* 验证token的有效性
* 说明:
* 1、解密接口在返回播放密钥前需要先校验Token的合法性和有效性
* 2、强烈建议同时校验Token的过期时间以及Token的有效使用次数
* @param token
* @return
* @throws Exception
*/
public boolean validateToken(String token) throws Exception {
if (null == token || "".equals(token)) {
return false;
}
String base = decrypt(token); //arg1为解密字符串arg2为解密Key
//先校验token的有效时间
Long expireTime = Long.valueOf(base.substring(base.lastIndexOf("_") + 1));
// System.out.println("时间校验:" + expireTime);
if (System.currentTimeMillis() > expireTime) {
return false;
}
//从DB获取token信息判断token的有效性业务方可自行实现
VodAesTokenEntity dbToken = getToken(token);
//判断是否已经使用过该token
if (dbToken == null || dbToken.getUseCount() > 0) {
return false;
}
dbToken.setUseCount(1);
vodAesTokenDao.updateById(dbToken);
//获取到业务属性信息,用于校验
String businessInfo = base.substring(0, base.lastIndexOf("_"));
String[] items = businessInfo.split("_");
//校验业务信息的合法性,业务方实现
return validateInfo(items);
}
/**
* 保存Token到DB
* 业务方自行实现
*
* @param token
*/
public void saveToken(String token) {
VodAesTokenEntity vodAesTokenEntity = new VodAesTokenEntity();
vodAesTokenEntity.setToken(token);
vodAesTokenDao.insert(vodAesTokenEntity);
//TODO 存储Token
}
/**
* 查询Token
* 业务方自行实现
*
* @param token
*/
public VodAesTokenEntity getToken(String token) {
List<VodAesTokenEntity> vodAesTokenEntities = vodAesTokenDao.selectList(new LambdaQueryWrapper<VodAesTokenEntity>().eq(VodAesTokenEntity::getToken, token));
if(vodAesTokenEntities.size()!=1){
return null;
}else{
return vodAesTokenEntities.get(0);
}
}
/**
* 校验业务信息的有效性,业务方可自行实现
*
* @param infos
* @return
*/
private boolean validateInfo(String... infos) {
//TODO 校验信息的有效性例如UID是否有效等
return true;
}
public static String encrypt(String value) {
try {
IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(ENCRYPT_KEY.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
// 使用 URL 安全的 Base64 编码
return Base64.getUrlEncoder().encodeToString(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(ENCRYPT_KEY.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
// 使用 URL 安全的 Base64 解码
byte[] original = cipher.doFinal(Base64.getUrlDecoder().decode(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
/**
* AES加密生成Token
*
* @param encryptStr 要加密的字符串
* @param encryptKey 加密Key
* @return
* @throws Exception
*/
// public String encrypt(String encryptStr, String encryptKey) throws Exception {
// IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
// SecretKeySpec skeySpec = new SecretKeySpec(encryptKey.getBytes("UTF-8"), "AES");
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// cipher.init(Cipher.ENCRYPT_MODE, skeySpec, e);
// byte[] encrypted = cipher.doFinal(encryptStr.getBytes());
// return Base64.encodeBase64String(encrypted);
// }
//
//
// /**
// * AES解密token
// *
// * @param encryptStr 解密字符串
// * @param decryptKey 解密Key
// * @return
// * @throws Exception
// */
// public String decrypt(String encryptStr, String decryptKey) throws Exception {
//
// IvParameterSpec e = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
// SecretKeySpec skeySpec = new SecretKeySpec(decryptKey.getBytes("UTF-8"), "AES");
// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// cipher.init(Cipher.DECRYPT_MODE, skeySpec, e);
//
// byte[] encryptByte = Base64.decodeBase64(encryptStr);
// byte[] decryptByte = cipher.doFinal(encryptByte);
// return new String(decryptByte);
// }
}