由于官方之提供了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()));