【问题标题】:Generate Azure Blob SAS token with APEX使用 APEX 生成 Azure Blob SAS 令牌
【发布时间】:2020-03-22 10:06:03
【问题描述】:

我想根据 Azure Doc 生成 SAS 令牌,以下是 BLOB 的示例。我仍然收到错误。你能确定我在做什么错吗?

StringToSign = signedpermissions + "\n" +  
               signedstart + "\n" +  
               signedexpiry + "\n" +  
               canonicalizedresource + "\n" +  
               signedidentifier + "\n" +  
               signedIP + "\n" +  
               signedProtocol + "\n" +  
               signedversion + "\n" +  
               rscc + "\n" +  
               rscd + "\n" +  
               rsce + "\n" +  
               rscl + "\n" +  
               rsct

网址 = https://myaccount.blob.core.windows.net/mycontainer/test.txt
canonicalizedresource = "/blob/myaccount/mycontainer/test.txt

我收到以下错误

<?xml version="1.0" encoding="utf-8"?>
<Error>
    <Code>AuthenticationFailed</Code>
    <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:4b1d1c59-c01e-0052-0197-ffe09f000000
Time:2020-03-21T15:44:34.2757923Z</Message>
    <AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>  

以下是我的代码

public void getSasToken() {

    this.storageName = 'zaindevtesting';
    this.storageContainer = 'zaindevblob';
    this.storageKey = 'xxxxxxZFQ==';
    this.storageUrl ='https://zaindevtesting.blob.core.windows.net';

    Datetime sasExpiry = Datetime.now();
    sasExpiry.addMinutes(15);
    Datetime sasStart = Datetime.now();
    sasStart.addMinutes(-5);


    string signedpermissions = 'rwdlac';
    String signedstart = sasStart.formatGMT('YYYY-MM-dd\'T\'HH:mm:ss\'Z\'');
    string signedexpiry = sasExpiry.formatGMT('YYYY-MM-dd\'T\'HH:mm:ss\'Z\'');
    string signedservice = 'b';
    String canonicalizedresource = '/blob/zaindevtesting/zaindevblob/test.txt';
    string signedidentifier = '';
    string signedIP = '';
    string signedProtocol = 'https';
    string signedversion = '2015-04-05';
    string rscc='';
    string rscd='';
    string rsce='';
    string rscl='';
    string rsct='';


    string stringToSign =signedpermissions + '\n' +  
               signedstart + '\n' +  
               signedexpiry + '\n' +  
               canonicalizedresource + '\n' +  
               signedidentifier + '\n' +  
               signedIP + '\n' +  
               signedProtocol + '\n' +  
               signedversion + '\n' +  
               rscc + '\n' +  
               rscd + '\n' +  
               rsce + '\n' +  
               rscl + '\n' +  
               rsct;

    string signedExpiryEncode = EncodingUtil.urlEncode(signedexpiry, 'UTF-8'); 
    string signedStartEncode = EncodingUtil.urlEncode(signedstart, 'UTF-8'); 
    String sasToken = '';
    Blob unicodeKey = EncodingUtil.base64Decode(storageKey);
    Blob data = Crypto.generateMac('HMACSHA256', Blob.valueOf(stringToSign), unicodeKey);
    sasToken = EncodingUtil.base64Encode(data);
    String sasTokenString= '?sv=' + signedversion + '&se=' + signedexpiry +'&st='+signedstart+'&sr='+signedservice+'&sp=' + signedpermissions + '&sig=' + sasToken;

    string sasURL = 'https://zaindevtesting.blob.core.windows.net/test.txt'+sasTokenString;
    System.debug('sasURL--->'+sasURL);
    System.debug(sasTokenString);
   // return sasToken;
}

此代码生成以下 SAS 链接

https://zaindevtesting.blob.core.windows.net/test.txt??sv=2017-11-09&st=2020-03-21T15%3A44%3A07Z&se=2020-03-21T15%3A44%3A07Z&sr=b&sp=rwdc&sig=eJVbGWI4rcyjggOYAE308ilXEA/zAsFYbuNi24IZhX4=

【问题讨论】:

    标签: azure salesforce blob apex


    【解决方案1】:

    请尝试以下代码:

    public void generateSASToken()
    {
        string storageName = 'zaindevtesting';
        string storageContainer = 'zaindevblob';
        string storageKey = 'xxxx==';
        string storageUrl ='https://zaindevtesting.blob.core.windows.net';
    
        Datetime sasExpiry = Datetime.now();
        sasExpiry = sasExpiry.addMinutes(15);
        Datetime sasStart = Datetime.now();
        sasStart = sasStart.addMinutes(-5);
    
    
        string signedpermissions = 'r';
        String signedstart = sasStart.formatGMT('YYYY-MM-dd\'T\'HH:mm:ss\'Z\'');
        string signedexpiry = sasExpiry.formatGMT('YYYY-MM-dd\'T\'HH:mm:ss\'Z\'');
        string signedservice = 'b';
        String canonicalizedresource = '/blob/zaindevtesting/zaindevblob/test.txt';
        string signedidentifier = '';
        string signedIP = '';
        string signedProtocol = '';
        string signedversion = '2015-04-05';
        string rscc='';
        string rscd='';
        string rsce='';
        string rscl='';
        string rsct='';
    
    
        string stringToSign =signedpermissions + '\n' +  
            signedstart + '\n' +  
            signedexpiry + '\n' +  
            canonicalizedresource + '\n' +  
            signedidentifier + '\n' +  
            signedIP + '\n' +  
            signedProtocol + '\n' +  
            signedversion + '\n' +  
            rscc + '\n' +  
            rscd + '\n' +  
            rsce + '\n' +  
            rscl + '\n' +  
            rsct;
        System.debug('stringToSign--->'+stringToSign);
        string signedExpiryEncode = EncodingUtil.urlEncode(signedexpiry, 'UTF-8'); 
        string signedStartEncode = EncodingUtil.urlEncode(signedstart, 'UTF-8'); 
        String sasToken = '';
        Blob unicodeKey = EncodingUtil.base64Decode(storageKey);
        Blob data = Crypto.generateMac('HMACSHA256', Blob.valueOf(stringToSign), unicodeKey);
        sasToken = EncodingUtil.base64Encode(data);
        sasToken = EncodingUtil.urlEncode(sasToken, 'UTF-8');        
        String sasTokenString= '?sv=' + signedversion + '&se=' + signedexpiry +'&st='+signedstart+'&sr='+signedservice+'&sp=' + signedpermissions + '&sig=' + sasToken;
    
        string sasURL = 'https://zaindevtesting.blob.core.windows.net/zaindevblob/test.txt'+sasTokenString;
        System.debug('sasURL--->'+sasURL);
        System.debug(sasTokenString);
        // return sasToken;
    }
    

    我刚刚使用您的存储帐户密钥进行了尝试,并且能够下载 blob。

    发现您的代码存在以下问题:

    • 权限必须按特定顺序排列。您正在使用string signedpermissions = 'rwdlac';,这不是正确的顺序。我刚刚指定了read 权限。
    • 签名协议在stringToString 中指定,但未包含在 SAS URL 中。我在这两个地方都省略了。
    • SAS 令牌未进行 URL 编码。
    • 您为zaindevtesting.blob.core.windows.net/zaindevblob/test.txt URL 生成了 SAS 令牌,但忘记在最终 URL 中包含 blob 容器名称。

    【讨论】:

    • 谢谢@Gaurav Mantri 您的解决方案,我还有一个问题。有没有什么方法可以在没有任何 Node Js 语法的情况下使用 Azure Javascript SDK?我想在闪电网络组件中使用该 SDK。但大多数 Microsoft Doc 示例都有 Node Js 语法
    • 太棒了!我很高兴听到这个消息......它已经困扰你很长一段时间了:)。关于您关于使用 JS SDK 的问题,绝对可以。相同的 SDK 应该也可以在浏览器中运行。
    • 对于未来的解决方案/问题查找器,如果您使用 SAS 令牌进行上传,请使用 string signedpermissions = 'w'; // 写权限。根据 Azure Doc,也有很多。其中 Read=r、Write=w、Delete=d、Create=c 和 List=l
    • @ Gaurav Mantri 是的,它困扰了一段时间,但我能够使用共享密钥解决问题,为此我还更新了我以前的帖子以供其他人将来参考。这种方法的唯一问题是,我无法从 APEX 代码上传大 Blob。所以这就是我需要使用 Javascript 上传和我将从 APEX 代码生成的 SAS 令牌的原因。
    猜你喜欢
    • 2018-08-14
    • 2018-12-12
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多