由于官方之提供了php版本,故此提供java版本给大家使用
伸手党 福利
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.UUID;
import java.util.logging.Logger;
/**
* 阿里云cdn 鉴权加密工具
* <p>有效时间1800s指用户访问客户源服务器时间超过自定义失效时间(timestamp字段指定)的1800s后,该鉴权失效</p>
* <p>例如用户设置访问时间为2020-08-15 15:00:00,则链接的真正失效时间为2020-08-15 15:30:00。</p>
* <p>url中特殊字符进行转码,避免中文路径异常</p>
*
* @author douhuatong
* @since 2019-03-06 15:02
*/
public class AliyunCndUrlAccessUtil {
static final String ENCODING = "utf-8";
private static final DateTimeFormatter YYYYMMDDHHMM = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
private static final String hexDigIts[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
/**
* A方式鉴权
* <P>https://help.aliyun.com/document_detail/85113.html?spm=a2c4g.11186623.6.604.5d708d48FTiaa8</P>
* 用户访问的 URL 如下: http://cdn.example.com/video/standard/1K.html?auth_key=1444435200-0-0-80cd3862d699b7118eed99103f2a3a4f
*
* @param domainName cnd域名
* @param privateKey cnd 加密key
* @param objectKey oss 对象key (注意,鉴权时候 objectKey 要以/开头)
* @param expiration 过期时间
*/
public static String signA(String domainName, String privateKey, String objectKey, Date expiration) {
if (isBlank(objectKey)) {
return "";
}
long es = expiration.getTime() / 1000;
String rand = UUID.randomUUID().toString().replace("-", "");
try {
objectKey = URLEncoder.encode(objectKey, ENCODING).replace("%2F", "/");
} catch (UnsupportedEncodingException e) {
}
if (!objectKey.startsWith("/")) {
objectKey = "/" + objectKey;
}
return domainName + objectKey + "?auth_key=" + es + "-" + rand + "-0-" + md5Hex(objectKey + "-" + es + "-" + rand + "-0-" + privateKey);
}
/**
* B方式鉴权
* <P>https://help.aliyun.com/document_detail/85114.html?spm=a2c4g.11186623.6.596.705c100bXExQvg</P>
* 用户访问的 URL 如下: 试用 http://DomainName/timestamp/md5hash/FileName 加密URL的构造:域名后跟生成URL的时间(精确到分钟)(timestamp)再跟md5值(md5hash),最后拼接回源服务器的真实路径(FileName),URL有效时间为1800s。
*
* 当鉴权通过时,实际回源的URL是: 试用 http://DomainName/FileName
*
* URL有效时间为1800s。
*
* @param domainName cnd域名
* @param privateKey cnd 加密key
* @param objectKey oss 对象key (注意,鉴权时候 objectKey 要以/开头)
* @param expiration 过期时间
*/
public static String signB(String domainName, String privateKey, String objectKey, Date expiration) {
if (isBlank(objectKey)) {
return "";
}
try {
objectKey = URLEncoder.encode(objectKey, ENCODING).replace("%2F", "/");
} catch (UnsupportedEncodingException e) {
}
if (!objectKey.startsWith("/")) {
objectKey = "/" + objectKey;
}
LocalDateTime localDateTime = LocalDateTime.ofInstant(expiration.toInstant(), ZoneId.systemDefault());
String now = localDateTime.format(YYYYMMDDHHMM);
return domainName + "/" + now + "/" + md5Hex(privateKey + now + objectKey) + objectKey;
}
/**
* C方式鉴权 1
* <P>https://help.aliyun.com/document_detail/85115.html?spm=a2c4g.11186623.6.606.5d708d481mQzCF</P>
* 用户访问的 URL http://DomainName/{/}/FileName
*
* @param domainName cnd域名
* @param privateKey cnd 加密key
* @param objectKey oss 对象key (注意,鉴权时候 objectKey 要以/开头)
* @param expiration 过期时间
*/
public static String signC1(String domainName, String privateKey, String objectKey, Date expiration) {
if (isBlank(objectKey)) {
return "";
}
try {
objectKey = URLEncoder.encode(objectKey, ENCODING).replace("%2F", "/");
} catch (UnsupportedEncodingException e) {
}
if (!objectKey.startsWith("/")) {
objectKey = "/" + objectKey;
}
String time = new BigInteger(String.valueOf(expiration.getTime() / 1000), 10).toString(16);
String md5 = md5Hex(privateKey + objectKey + time);
return domainName + "/" + md5 + "/" + time + objectKey;
}
/**
* C方式鉴权 2
* <P>https://help.aliyun.com/document_detail/85115.html?spm=a2c4g.11186623.6.606.5d708d481mQzCF</P>
* 用户访问的 URL http://cdn.example.com/a37fa50a5fb8f71214b1e7c95ec7a1bd/55CE8100/test.flv
*
* @param domainName cnd域名
* @param privateKey cnd 加密key
* @param objectKey oss 对象key
* @param expiration 过期时间
*/
public static String signC2(String domainName, String privateKey, String objectKey, Date expiration) {
if (isBlank(objectKey)) {
return "";
}
try {
objectKey = URLEncoder.encode(objectKey, ENCODING).replace("%2F", "/");
} catch (UnsupportedEncodingException e) {
}
if (!objectKey.startsWith("/")) {
objectKey = "/" + objectKey;
}
String time = new BigInteger(String.valueOf(expiration.getTime() / 1000), 10).toString(16);
String md5 = md5Hex(privateKey + objectKey + time);
return domainName + objectKey + "?KEY1=" + md5 + "&KEY2=" + time;
}
public static boolean isBlank(final CharSequence cs) {
int strLen;
if (cs == null || (strLen = cs.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(cs.charAt(i))) {
return false;
}
}
return true;
}
private static String md5Hex(String origin) {
String resultString = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
resultString = byteArrayToHexString(md.digest(origin.getBytes(ENCODING)));
} catch (Exception e) {
}
return resultString;
}
private static String byteArrayToHexString(byte[] b) {
StringBuilder resultSb = new StringBuilder();
for (byte b1 : b) {
resultSb.append(byteToHexString(b1));
}
return resultSb.toString();
}
private 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) {
String key = "123";
String domain = "http://xxx.aaa.com";
String ossKey = "xxx.pdf";
System.err.println("A=: " + signA(domain, key, ossKey, new Date()));
System.err.println("B=: " + signB(domain, key, ossKey, new Date()));
System.err.println("C-1=: " + signC1(domain, key, ossKey, new Date()));
System.err.println("C-2=: " + signC2(domain, key, ossKey, new Date()));
}
}