我想生成一个 SAS 令牌来访问我的 Blob 容器,其中包含我的一些媒体文件。
\n\n所以我使用以下代码创建了一个 SharedAccessSignature.java 类:
\n\npublic class SharedAccessSignature\n{\n private final String signature;\n\n private final String signedPermission;\n private final String signedStart;\n private final String signedExpiry;\n private final String signedIdentifier;\n private final String signedIp;\n private final String signedProtocol;\n private final String signedVersion;\n private final String signedResource;\n\n private SharedAccessSignature(SasBuilder builder)\n {\n signedPermission = formatAsUrlParameter("sp", builder.signedPermission);\n signedStart = formatAsUrlParameter("st", builder.signedStart);\n signedExpiry = formatAsUrlParameter("se", builder.signedExpiry);\n signedIdentifier = formatAsUrlParameter("si", builder.signedIdentifier);\n signedIp = formatAsUrlParameter("sip", builder.signedIp);\n signedProtocol = formatAsUrlParameter("spr", builder.signedProtocol);\n signedVersion = formatAsUrlParameter("sv", builder.signedVersion);\n signedResource = formatAsUrlParameter("sr", builder.signedResource);\n\n signature = "sig=" + new SasBuilder().encodeUtf8(builder.signature);\n }\n\n private String formatAsUrlParameter(String parameterKey, String parameterValue)\n {\n if (StringUtils.isNotBlank(parameterValue))\n {\n return parameterKey + "=" + parameterValue + "&";\n }\n return "";\n }\n\n @Override\n public String toString()\n {\n return new StringBuilder()\n .append(signedVersion)\n .append(signedResource)\n .append(signedStart)\n .append(signedExpiry)\n .append(signedPermission)\n .append(signedIp)\n .append(signedProtocol)\n .append(signedIdentifier)\n .append(signature)\n .toString();\n }\n\n public static class SasBuilder\n {\n private String signature = "";\n\n private String signedPermission = "";\n private String signedStart = "";\n private String signedExpiry = "";\n private String canonicalizedResource = "";\n private String signedIdentifier = "";\n private String signedIp = "";\n private String signedProtocol = "";\n private String signedVersion = "";\n private String signedResource = "";\n\n public SasBuilder signedVersion(String signedVersion)\n {\n this.signedVersion = signedVersion;\n return this;\n }\n\n public SasBuilder signedPermission(String signedPermission)\n {\n this.signedPermission = signedPermission;\n return this;\n }\n\n public SasBuilder canonicalizedResource(String canonicalizedResource)\n {\n this.canonicalizedResource = canonicalizedResource;\n return this;\n }\n\n public SasBuilder signedIp(String signedIp)\n {\n this.signedIp = signedIp;\n return this;\n }\n\n public SasBuilder signedProtocol(String signedProtocol)\n {\n this.signedProtocol = signedProtocol;\n return this;\n }\n\n public SasBuilder signedIdentifier(String signedIdentifier)\n {\n this.signedIdentifier = signedIdentifier;\n return this;\n }\n\n public SasBuilder signedExpiry(String signedExpiry)\n {\n this.signedExpiry = signedExpiry;\n return this;\n }\n\n public SasBuilder signedStart(String signedStart)\n {\n this.signedStart = signedStart;\n return this;\n }\n\n public SasBuilder signedResource(String signedResource)\n {\n this.signedResource = signedResource;\n return this;\n }\n\n public SharedAccessSignature build()\n {\n String toBeAsEnvironmentVariable_securityKey = "....";\n signature = generateSasSignature(toBeAsEnvironmentVariable_securityKey, stringToSign());\n checkPreconditions();\n return new SharedAccessSignature(this);\n }\n\n private String generateSasSignature(String key, String input)\n {\n SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");\n Encoder encoder = Base64.getEncoder();\n Mac sha256_HMAC = null;\n String hash = null;\n\n try\n {\n sha256_HMAC = Mac.getInstance("HmacSHA256");\n sha256_HMAC.init(secret_key);\n hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));\n }\n catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | UnsupportedEncodingException e)\n {\n e.printStackTrace();\n }\n return hash;\n }\n\n private String stringToSign()\n {\n StringBuilder strToSign = new StringBuilder();\n strToSign.append(signedPermission).append("\\n");\n strToSign.append(signedStart).append("\\n");\n strToSign.append(signedExpiry).append("\\n");\n strToSign.append(canonicalizedResource).append("\\n");\n strToSign.append(signedIdentifier).append("\\n");\n strToSign.append(signedIp).append("\\n");\n strToSign.append(signedProtocol).append("\\n");\n strToSign.append(signedVersion).append("\\n");\n strToSign.append("").append("\\n");\n strToSign.append("").append("\\n");\n strToSign.append("").append("\\n");\n strToSign.append("").append("\\n");\n strToSign.append("");\n return strToSign.toString();\n }\n\n private void checkPreconditions()\n {\n if (StringUtils.isBlank(signedVersion) || StringUtils.isBlank(signedResource) || StringUtils.isBlank(signedPermission) || StringUtils.isBlank(signedExpiry) || StringUtils.isBlank(signature))\n {\n throw new IllegalStateException("SAS Builder: SignedVersion, signedResource, SignedPermission, SignedExpiry, Signature must be set.");\n }\n }\n\n private String encodeUtf8(String textToBeEncoded)\n {\n try\n {\n return URLEncoder.encode(textToBeEncoded, "UTF-8");\n }\n catch (UnsupportedEncodingException e)\n {\n e.printStackTrace();\n }\n return textToBeEncoded;\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后我尝试生成一个 SAS 令牌,如下所示:
\n\nSharedAccessSignature s = new SharedAccessSignature.SasBuilder()\n .signedPermission("rwd")\n .signedStart("2018-01-31T10:48:41Z")\n .signedExpiry("2018-04-06T18:48:41Z")\n .signedVersion("2015-04-05")\n .signedResource("b")\n .canonicalizedResource("/blob/myaccount")\n .signedProtocol("https")\n .build();\nRun Code Online (Sandbox Code Playgroud)\n\n结果:
\n\nsv=2015-04-05&sr=b&st=2018-01-31T10:48:41Z&se=2018-04-06T18:48:41Z&sp=rwd&spr=https&sig=kd09Y%2FTL5V%2F570VWRuEfq7XbEHvcgo4Z%2F2y9t4OswY8%3D\nRun Code Online (Sandbox Code Playgroud)\n\n获取请求:
\n\nhttps://account.blob.core.cloudapi.de/container/filename.mp4?sv=2015-04-05&sr=b&st=2018-01-31T10:48:41Z&se=2018-04-06T18:48:41Z&sp=rwd&spr=https&sig=kd09Y%2FTL5V%2F570VWRuEfq7XbEHvcgo4Z%2F2y9t4OswY8%3D\nRun Code Online (Sandbox Code Playgroud)\n\n但是当我使用生成的令牌发送该请求时,天蓝色出现此错误:
\n\n<Error>\n <Code>AuthenticationFailed</Code>\n <Message>\n Server failed to authenticate the request. Make sure the value of \n Authorization header is formed correctly including the signature. \n </Message>\n <AuthenticationErrorDetail>\n Signature did not match. String to sign used was rwd 2018-01-31T10:48:41Z \n 2018-04-06T18:48:41Z /blob/globalweb/..... https 2015-04-05\n </AuthenticationErrorDetail>\n</Error>\nRun Code Online (Sandbox Code Playgroud)\n\n我很绝望......我不明白\xc2\xb4t明白......这个“签名字符串”有什么问题?为什么“签名不匹配”?
\n\n--------\nrwd\\n\n2018-01-31T10:48:41Z\\n\n2018-04-06T18:48:41Z\\n\n/blob/globalweb/videos-martindale\\n\n\\n\n\\n\nhttps\\n\n2015-04-05\\n\n\\n\n\\n\n\\n\n\\n\n\n-------\n\n//link: https://globalweb.blob.core.cloudapi.de/videos-martindale/somevideo.mp4?sv=2015-04-05&sr=c&st=2018-01-31T10:48:41Z&se=2018-04-06T18:48:41Z&sp=rwd&spr=https&sig=kd09Y%2FTL5V%2F570VWRuEfq7XbEHvcgo4Z%2F2y9t4OswY8%3D\n\n<Error>\n <Code>AuthenticationFailed</Code>\n <Message>\n Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:644e47a6-001e-0050-3f20-abc0f0000000 Time:2018-02-21T14:31:10.9429817Z\n </Message>\n <AuthenticationErrorDetail>\n Signature did not match. String to sign used was rwd 2018-01-31T10:48:41Z 2018-04-06T18:48:41Z /blob/globalweb/videos-martindale https 2015-04-05\n </AuthenticationErrorDetail>\n</Error>\nRun Code Online (Sandbox Code Playgroud)\n
主要问题出在你的generateSasSignature方法上。它应该从 中解码密钥Base64。就像下面这样:
public static String generateSasSignature(String key, String input) {
SecretKeySpec secret_key = new SecretKeySpec(Base64.getDecoder().decode(key), "HmacSHA256");
Encoder encoder = Base64.getEncoder();
Mac sha256_HMAC = null;
String hash = null;
try {
sha256_HMAC = Mac.getInstance("HmacSHA256");
sha256_HMAC.init(secret_key);
hash = new String(encoder.encode(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));
}
catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return hash;
}
Run Code Online (Sandbox Code Playgroud)
然后,假设您有兴趣访问名为 的容器mycontainer,那么您应该这样做:
SharedAccessSignature s = new SharedAccessSignature.SasBuilder()
.signedPermission("rwd")
.signedStart("2018-01-31T10:48:41Z")
.signedExpiry("2018-04-06T18:48:41Z")
.signedVersion("2015-04-05")
.signedResource("c") // <<---- note here
.canonicalizedResource("/blob/globalweb/mycontainer") // No ending slash!
.signedProtocol("https")
.build();
Run Code Online (Sandbox Code Playgroud)
但是,如果您想生成 Account SAS,可以使用以下代码:
public static void main(String[] args) throws UnsupportedEncodingException {
String accountName = "globalweb";
String signedPermissions = "rl"; //read and list
String signedService = "b"; //blob
String signedResType = "sco"; //service, container, objects
String start = "2018-02-22T17:16:25Z";
String expiry = "2018-02-28T01:16:25Z";
String signedIp = "";
String protocol = "https";
String signedVersion = "2017-07-29";
String stringToSign =
accountName + "\n" +
signedPermissions + "\n" +
signedService + "\n" +
signedResType + "\n" +
start + "\n" +
expiry + "\n" +
signedIp + "\n" +
protocol + "\n" +
signedVersion + "\n";
//outputs SAS Token
System.out.println(
"?sv="+signedVersion +
"&ss="+signedService +
"&srt="+signedResType +
"&sp="+signedPermissions +
"&st="+start+
"&se="+expiry+
"&spr="+protocol+
"&sig="+
URLEncoder.encode(SasBuilder.generateSasSignature(MY_KEY_BASE64, stringToSign), "UTF-8"));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11091 次 |
| 最近记录: |