我面临使用 AAD 令牌作为身份验证的邮递员获取容器 ACL 和设置容器 ACL REST API 的问题

Posted

技术标签:

【中文标题】我面临使用 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 【发布时间】:2021-12-21 09:08:14 【问题描述】:

我在使用 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>

不确定我缺少的是正确的权限还是正确的参数?

【问题讨论】:

【参考方案1】:

我使用AAD Authorization 方法进行了相同的测试,仅 ACL 操作遇到了同样的问题,而其他操作(如列表 blob)都成功了。

正如 @SumanthMarigowda-MSFT 所述,ACL 操作不支持 AAD auth。你必须使用Shared Key Auth

步骤:

    如下创建环境变量:

    注意:只提供高亮变量的初始值,其他变量留空。

    创建请求 https://azure_storage_account.blob.core.windows.net/yourcontainername?restype=container&amp;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`);
    

    然后保存并发送请求,您将得到如下输出:

预请求脚本参考:

Github

【讨论】:

【参考方案2】:

Get Container ACL & Set Container ACL 目前只支持 SharedKey 认证。它们不支持 AAD 身份验证。

【讨论】:

以上是关于我面临使用 AAD 令牌作为身份验证的邮递员获取容器 ACL 和设置容器 ACL REST API 的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jwt 的基于令牌的身份验证无法授权

使用邮递员 404 端点发现 api 身份验证

我是否可以使用AAD保护REST API(在春季启动时说)并从该AAD以用户身份访问它

azure 移动服务活动目录身份验证 X-ZUMO-AUTH 令牌在注销后在邮递员中有效

无法验证 AAD 访问令牌 - IDX10511:签名验证失败

Laravel OAuth2 Passport API,生成令牌但无法发出请求:“未经身份验证”