vod普通加密

This commit is contained in:
wangjinlei
2024-07-18 13:29:22 +08:00
parent 64702a8184
commit 00b9f96dd1
8 changed files with 297 additions and 1 deletions

View File

@@ -185,7 +185,11 @@
<artifactId>poi-ooxml-schemas</artifactId> <artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version> <version>3.17</version>
</dependency> </dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>sts20150401</artifactId>
<version>1.1.4</version>
</dependency>
<dependency> <dependency>
<groupId>com.aspose.words</groupId> <groupId>com.aspose.words</groupId>
<artifactId>aspose-words</artifactId> <artifactId>aspose-words</artifactId>

View File

@@ -0,0 +1,167 @@
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 org.apache.commons.codec.binary.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, ENCRYPT_KEY); //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,ENCRYPT_KEY); //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;
}
/**
* 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);
}
}

View File

@@ -5,6 +5,13 @@ import com.aliyun.teautil.models.RuntimeOptions;
import com.aliyun.vod20170321.Client; import com.aliyun.vod20170321.Client;
import com.aliyun.vod20170321.models.GetVideoPlayAuthRequest; import com.aliyun.vod20170321.models.GetVideoPlayAuthRequest;
import com.aliyun.vod20170321.models.GetVideoPlayAuthResponse; import com.aliyun.vod20170321.models.GetVideoPlayAuthResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
//import org.bytedeco.javacv.FFmpegFrameGrabber; //import org.bytedeco.javacv.FFmpegFrameGrabber;
//import org.bytedeco.javacv.FrameGrabber; //import org.bytedeco.javacv.FrameGrabber;
@@ -59,4 +66,53 @@ public class SpdbUtil {
} }
} }
public static AssumeRoleResponse assumeRole() throws ClientException {
try {
String accessKeyId = "LTAI5tC9d38msYxw6RSEwJJR";
String accessKeySecret = "njJxkvrwBmbMfGyhAFeyjthodnwt58";
String roleArn = "acs:ram::1604740137891907:role/vodrole";
String roleSessionName = "testsession";
String policy = "{\n" +
" \"Version\": \"1\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": \"vod:*\",\n" +
" \"Resource\": \"*\",\n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
//构造default profile参数留空无需添加Region ID
/*
说明当设置SysEndpoint为sts.aliyuncs.com时regionId可填可不填反之regionId必填根据使用的服务区域填写例如cn-shanghai
详情参考STS各地域的Endpoint。
*/
IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
//用profile构造client
DefaultAcsClient client = new DefaultAcsClient(profile);
// 创建一个 AssumeRoleRequest 并设置请求参数
final AssumeRoleRequest request = new AssumeRoleRequest();
// request.setSysEndpoint("sts.aliyuncs.com");
// request.setSysMethod(MethodType.POST);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy);
request.setRegionId("cn-shanghai");
// 发起请求并得到response
final AssumeRoleResponse response = client.getAcsResponse(request);
return response;
} catch (ClientException e) {
throw e;
}
}
} }

View File

@@ -0,0 +1,9 @@
package com.peanut.modules.common.dao;
import com.github.yulichang.base.MPJBaseMapper;
import com.peanut.modules.common.entity.VodAesTokenEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface VodAesTokenDao extends MPJBaseMapper<VodAesTokenEntity> {
}

View File

@@ -36,4 +36,6 @@ public class CourseCatalogueChapterVideoEntity {
private UserCourseVideoPositionEntity userCourseVideoPositionEntity; private UserCourseVideoPositionEntity userCourseVideoPositionEntity;
@TableField(exist = false) @TableField(exist = false)
private String videoUrl; private String videoUrl;
@TableField(exist = false)
private String Mp4Url;
} }

View File

@@ -0,0 +1,17 @@
package com.peanut.modules.common.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("vod_aes_token")
public class VodAesTokenEntity {
@TableId
private Integer id;
private String token;
private Integer useCount;
}

View File

@@ -1,8 +1,10 @@
package com.peanut.modules.sociology.controller; package com.peanut.modules.sociology.controller;
import com.aliyun.vod20170321.models.*; import com.aliyun.vod20170321.models.*;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peanut.common.utils.PlayToken;
import com.peanut.common.utils.R; import com.peanut.common.utils.R;
import com.peanut.common.utils.ShiroUtils; import com.peanut.common.utils.ShiroUtils;
import com.peanut.common.utils.SpdbUtil; import com.peanut.common.utils.SpdbUtil;
@@ -14,6 +16,7 @@ import com.peanut.modules.master.service.SysCourseDirectService;
import com.peanut.modules.sociology.service.CourseCatalogueChapterService; import com.peanut.modules.sociology.service.CourseCatalogueChapterService;
import com.peanut.modules.sociology.service.CourseService; import com.peanut.modules.sociology.service.CourseService;
import com.peanut.modules.sociology.service.CourseSociologyService; import com.peanut.modules.sociology.service.CourseSociologyService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@@ -42,6 +45,8 @@ public class CourseController {
@Autowired @Autowired
private UserCourseStudyingDao userCourseStudyingDao; private UserCourseStudyingDao userCourseStudyingDao;
@Autowired
private PlayToken playToken;
/** /**
* 获取用户最近学习课程列表 * 获取用户最近学习课程列表
@@ -193,6 +198,22 @@ public class CourseController {
return courseCatalogueChapterVideoService.checkVideo(video); return courseCatalogueChapterVideoService.checkVideo(video);
} }
@RequestMapping("/mytt")
public R mytt() throws Exception {
String s = playToken.generateToken();
System.out.println(s);
boolean b = playToken.validateToken(s);
System.out.println(b);
return R.ok();
}
@RequestMapping("/ttt")
@SneakyThrows
public R ttt(){
AssumeRoleResponse assumeRoleResponse = SpdbUtil.assumeRole();
return R.ok().put("result",assumeRoleResponse);
}
@RequestMapping("/getMyCourse") @RequestMapping("/getMyCourse")
public R getMyCourse(@RequestBody Map<String,Integer> map){ public R getMyCourse(@RequestBody Map<String,Integer> map){
List courses = courseService.getMyCourse(map.get("type")); List courses = courseService.getMyCourse(map.get("type"));

View File

@@ -0,0 +1,20 @@
package com.peanut.modules.sys.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/sys/vodAli")
public class VodAliController {
@RequestMapping("/vodAliVideoRe")
public void vodAliVideoRe(@RequestBody Map<String,Object> map){
}
}