我在使用邮递员使用 AAD 令牌作为身份验证时遇到获取容器 ACL 和设置容器 ACL REST API 的问题
I am facing issues for Get Container ACL and Set Container ACL REST API using postman using AAD Token as authentication
我在使用 Postman 对 Get Container ACL 进行 REST API 调用时遇到以下错误:
<?xml version="1.0" encoding="utf-8"?>
<Error>
<Code>ResourceNotFound</Code>
<Message>The specified resource does not exist.
RequestId:35678849-101e-005b-0fa8-d4c9bd000000
Time:2021-11-08T13:53:42.8102881Z</Message>
</Error>
使用 Postman 对 Set Container ACL 进行 REST 调用时出现以下错误:
<?xml version="1.0" encoding="utf-8"?>
<Error>
<Code>ResourceNotFound</Code>
<Message>The specified resource does not exist.
RequestId:35688854-101e-005b-12a8-d4c9bd000000
Time:2021-11-08T13:58:12.8507122Z</Message>
</Error>
不确定我缺少的是正确的权限还是正确的参数?
Get Container ACL & Set Container ACL暂时只支持SharedKey认证。他们不支持 AAD 身份验证。
我使用 AAD Authorization
方法进行了相同的测试,仅 ACL 操作遇到了同样的问题,而其他操作(如 list blob)却成功了。
如 @SumanthMarigowda-MSFT 所述,ACL 操作不支持 AAD auth
。你必须使用 Shared Key Auth
.
步骤:
创建如下环境变量:
注意:只提供高亮变量的初始值,其他留空。
创建请求
https://{{azure_storage_account}}.blob.core.windows.net/yourcontainername?restype=container&comp=acl
根据您的要求 Get/Put
并添加以下内容
headers
:
在 Postman 的 Pre-Request Script
选项卡中添加以下代码:
const crypto = require("crypto-js");
// Set Date header value for authorization
// Should be UTC GMT string
pm.environment.set("header_date", new Date().toUTCString());
console.log("header date", new Date().toUTCString());
var substituteEnvVars = function (varStr) {
let match;
let replacedVar = varStr;
while ((match = /\{\{([^{}]*?)}}/g.exec(replacedVar)) !== null ) {
if (!pm.variables.get(match[1])) {
continue;
}
var envVar = new RegExp(RegExp.escape(match[0]), 'g');
replacedVar = replacedVar.replace(envVar, pm.variables.get(match[1]));
}
return replacedVar;
};
// Get hash of all header-name:value
const headers = pm.request.getHeaders({ ignoreCase: true, enabled: true });
// Construct Signature value for Authorization header
var signatureParts = [
pm.request.method.toUpperCase(),
headers["content-encoding"] || "",
headers["content-language"] || "",
pm.request.body.toString().length || "",
headers["content-md5"] || "",
headers["content-type"] || "",
headers["x-ms-date"] ? "" : (pm.variables.get("header_date") || ""),
headers["if-modified-since"] || "",
headers["if-match"] || "",
headers["if-none-match"] || "",
headers["if-unmodified-since"] || "",
headers["range"] || ""
];
// Construct CanonicalizedHeaders
const canonicalHeaderNames = [];
Object.keys(headers).forEach(key => {
if (key.startsWith("x-ms-")) {
canonicalHeaderNames.push(key);
console.log("key: ", canonicalHeaderNames);
}
});
// Sort headers lexographically by name
canonicalHeaderNames.sort();
const canonicalHeaderParts = [];
canonicalHeaderNames.forEach(key => {
let value = pm.request.getHeaders({ ignoreCase: true, enabled: true })[key];
console.log("value: ",value);
// Populate variables
value = substituteEnvVars(value);
console.log("value: ",value);
// Replace whitespace in value but not if its within quotes
if (!value.startsWith("\"")) {
value = value.replace(/\s+/, " ");
console.log("value: ",value);
}
canonicalHeaderParts.push(`${key}:${value}`);
console.log("canonicalHeaderParts: ",canonicalHeaderParts);
});
// Add headers to signature
signatureParts.push.apply(signatureParts, canonicalHeaderParts);
// Construct CanonicalizedResource
const canonicalResourceParts = [
`/${pm.environment.get("azure_storage_account")}${pm.request.url.getPath()}`
];
console.log("canonicalResourceParts: ",canonicalResourceParts);
const canonicalQueryNames = [];
pm.request.url.query.each(query => {
canonicalQueryNames.push(query.key.toLowerCase());
console.log("canonicalQueryNames: ",query.key.toLowerCase());
});
canonicalQueryNames.sort();
canonicalQueryNames.forEach(queryName => {
const value = pm.request.url.query.get(queryName);
console.log("canonicalQueryNames: ",value);
// NOTE: This does not properly explode multiple same query params' values
// and turn them into comma-separated list
canonicalResourceParts.push(`${queryName}:${value}`);
console.log("canonicalResourcePartss: ",canonicalResourceParts);
});
// Add resource to signature
signatureParts.push.apply(signatureParts, canonicalResourceParts);
console.log("Signature Parts", signatureParts);
// Now, construct signature raw string
const signatureRaw = signatureParts.join("\n");
console.log("Signature String", JSON.stringify(signatureRaw));
// Hash it using HMAC-SHA256 and then encode using base64
const storageKey = pm.environment.get("azure_storage_key");
const signatureBytes = crypto.HmacSHA256(signatureRaw, crypto.enc.Base64.parse(storageKey));
const signatureEncoded = signatureBytes.toString(crypto.enc.Base64);
console.log("Storage Account", pm.environment.get("azure_storage_account"));
console.log("Storage Key", storageKey);
// Finally, make it available for headers
pm.variables.set("header_authorization",
`SharedKey ${pm.environment.get("azure_storage_account")}:${signatureEncoded}`);
然后保存并发送请求,您将得到如下输出:
预请求脚本参考:
我在使用 Postman 对 Get Container ACL 进行 REST API 调用时遇到以下错误:
<?xml version="1.0" encoding="utf-8"?>
<Error>
<Code>ResourceNotFound</Code>
<Message>The specified resource does not exist.
RequestId:35678849-101e-005b-0fa8-d4c9bd000000
Time:2021-11-08T13:53:42.8102881Z</Message>
</Error>
使用 Postman 对 Set Container ACL 进行 REST 调用时出现以下错误:
<?xml version="1.0" encoding="utf-8"?>
<Error>
<Code>ResourceNotFound</Code>
<Message>The specified resource does not exist.
RequestId:35688854-101e-005b-12a8-d4c9bd000000
Time:2021-11-08T13:58:12.8507122Z</Message>
</Error>
不确定我缺少的是正确的权限还是正确的参数?
Get Container ACL & Set Container ACL暂时只支持SharedKey认证。他们不支持 AAD 身份验证。
我使用 AAD Authorization
方法进行了相同的测试,仅 ACL 操作遇到了同样的问题,而其他操作(如 list blob)却成功了。
如 @SumanthMarigowda-MSFT 所述,ACL 操作不支持 AAD auth
。你必须使用 Shared Key Auth
.
步骤:
创建如下环境变量:
注意:只提供高亮变量的初始值,其他留空。
创建请求
https://{{azure_storage_account}}.blob.core.windows.net/yourcontainername?restype=container&comp=acl
根据您的要求Get/Put
并添加以下内容headers
:在 Postman 的
Pre-Request Script
选项卡中添加以下代码:const crypto = require("crypto-js"); // Set Date header value for authorization // Should be UTC GMT string pm.environment.set("header_date", new Date().toUTCString()); console.log("header date", new Date().toUTCString()); var substituteEnvVars = function (varStr) { let match; let replacedVar = varStr; while ((match = /\{\{([^{}]*?)}}/g.exec(replacedVar)) !== null ) { if (!pm.variables.get(match[1])) { continue; } var envVar = new RegExp(RegExp.escape(match[0]), 'g'); replacedVar = replacedVar.replace(envVar, pm.variables.get(match[1])); } return replacedVar; }; // Get hash of all header-name:value const headers = pm.request.getHeaders({ ignoreCase: true, enabled: true }); // Construct Signature value for Authorization header var signatureParts = [ pm.request.method.toUpperCase(), headers["content-encoding"] || "", headers["content-language"] || "", pm.request.body.toString().length || "", headers["content-md5"] || "", headers["content-type"] || "", headers["x-ms-date"] ? "" : (pm.variables.get("header_date") || ""), headers["if-modified-since"] || "", headers["if-match"] || "", headers["if-none-match"] || "", headers["if-unmodified-since"] || "", headers["range"] || "" ]; // Construct CanonicalizedHeaders const canonicalHeaderNames = []; Object.keys(headers).forEach(key => { if (key.startsWith("x-ms-")) { canonicalHeaderNames.push(key); console.log("key: ", canonicalHeaderNames); } }); // Sort headers lexographically by name canonicalHeaderNames.sort(); const canonicalHeaderParts = []; canonicalHeaderNames.forEach(key => { let value = pm.request.getHeaders({ ignoreCase: true, enabled: true })[key]; console.log("value: ",value); // Populate variables value = substituteEnvVars(value); console.log("value: ",value); // Replace whitespace in value but not if its within quotes if (!value.startsWith("\"")) { value = value.replace(/\s+/, " "); console.log("value: ",value); } canonicalHeaderParts.push(`${key}:${value}`); console.log("canonicalHeaderParts: ",canonicalHeaderParts); }); // Add headers to signature signatureParts.push.apply(signatureParts, canonicalHeaderParts); // Construct CanonicalizedResource const canonicalResourceParts = [ `/${pm.environment.get("azure_storage_account")}${pm.request.url.getPath()}` ]; console.log("canonicalResourceParts: ",canonicalResourceParts); const canonicalQueryNames = []; pm.request.url.query.each(query => { canonicalQueryNames.push(query.key.toLowerCase()); console.log("canonicalQueryNames: ",query.key.toLowerCase()); }); canonicalQueryNames.sort(); canonicalQueryNames.forEach(queryName => { const value = pm.request.url.query.get(queryName); console.log("canonicalQueryNames: ",value); // NOTE: This does not properly explode multiple same query params' values // and turn them into comma-separated list canonicalResourceParts.push(`${queryName}:${value}`); console.log("canonicalResourcePartss: ",canonicalResourceParts); }); // Add resource to signature signatureParts.push.apply(signatureParts, canonicalResourceParts); console.log("Signature Parts", signatureParts); // Now, construct signature raw string const signatureRaw = signatureParts.join("\n"); console.log("Signature String", JSON.stringify(signatureRaw)); // Hash it using HMAC-SHA256 and then encode using base64 const storageKey = pm.environment.get("azure_storage_key"); const signatureBytes = crypto.HmacSHA256(signatureRaw, crypto.enc.Base64.parse(storageKey)); const signatureEncoded = signatureBytes.toString(crypto.enc.Base64); console.log("Storage Account", pm.environment.get("azure_storage_account")); console.log("Storage Key", storageKey); // Finally, make it available for headers pm.variables.set("header_authorization", `SharedKey ${pm.environment.get("azure_storage_account")}:${signatureEncoded}`);
然后保存并发送请求,您将得到如下输出:
预请求脚本参考: