Azure 文件共享 SAS 令牌签名未按预期生成,如何为文件对象生成签名以匹配门户中生成的签名?

Posted

技术标签:

【中文标题】Azure 文件共享 SAS 令牌签名未按预期生成,如何为文件对象生成签名以匹配门户中生成的签名?【英文标题】:Azure File share SAS token signature not generating as expected, How do one generate signature for file object to match the one generated in portal? 【发布时间】:2021-03-05 20:10:55 【问题描述】:

我正在尝试以编程方式为 SAS 令牌创建一个签名,当用户选择几个选项时,该签名应该与 azure 门户中生成的签名相匹配。但是,文档非常混乱,并不能指导您实现操作所需的内容。我在 azure 文件共享中有一个文件,我想通过生成 SAS 令牌并对其进行签名来访问它。我可以通过在 Azure 门户中选择适当的选项并访问文件来轻松地做到这一点,但我想以编程方式完成确切的事情。我用 java 试过,但结果 SAS 令牌签名不匹配。请帮帮我。

下面是我通过 Azure 门户生成的 SAS 令牌:

?sv=2019-12-12&ss=f&srt=o&sp=r&se=2020-11-23T12:20:39Z&st=2020-11-23T04:20:39Z&spr=https&sig=XI%2FlSZSXp54XVwk2G%2F23j%2FjqsrojVqJoAonh6gdaAPk%3D

在azure portal中为上述sas token选择的对应选项如下图所示

使用的密钥是key1,如下:

l1wxekiJj9IcTw350w5c1MtVfYVP3qcz3zdxzCCp+YVaXqs9faOJfl/Z07AoLDnsnyn+POGjxjcFy3EF9g/r9Q==

我尝试的是为以下选项(要签名的字符串)生成签名,该签名取自 azure 门户生成的 SAS 令牌并使用上面的 key1。

sv=2019-12-12&ss=f&srt=o&sp=r&se=2020-11-23T12:20:39Z&st=2020-11-23T04:20:39Z&spr=https

下面是我的java代码,它为上面的字符串生成签名

import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
public class GenerateSAS 
    public static void main(String[] args) throws Exception
        Mac sha256_HMAC = null;
        String hash = null;
        String input="sv=2019-12-12&ss=f&srt=o&sp=r&se=2020-11-23T12:20:39Z&st=2020-11-23T04:20:39Z&spr=https";
        input=URLEncoder.encode(input, "UTF-8");
        String key="l1wxekiJj9IcTw350w5c1MtVfYVP3qcz3zdxzCCp+YVaXqs9faOJfl/Z07AoLDnsnyn+POGjxjcFy3EF9g/r9Q==";
        sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        hash = new String(Base64.encodeBase64(sha256_HMAC.doFinal(input.getBytes("UTF-8"))));
        System.out.println(hash);
    

上面的代码生成的签名是MK/uu+NlURscoX1dymzipRN/Jb4aXyVzfbIVBz8l02M=,这不等于在azure门户中生成的签名是XI%2FlSZSXp54XVwk2G%2F23j%2FjqsrojVqJoAonh6gdaAPk%3D

请帮助我正确生成签名,这将帮助我将其附加到 SAS 令牌以进行文件对象访问。

【问题讨论】:

【参考方案1】:

如果要创建 sas 令牌来访问 Azure 文件服务资源,签名字符串应如下所示。更多详情请参考here

StringToSign = accountname + "\n" +  
    signedpermissions + "\n" +  
    signedservice + "\n" +  
    signedresourcetype + "\n" +  
    signedstart + "\n" +  
    signedexpiry + "\n" +  
    signedIP + "\n" +  
    signedProtocol + "\n" +  
    signedversion + "\n"  

例如

 public static void createSasToken()

    String accountName = "accountName";
    String key = "accountKey";
    String resourceUrl = "https://"+accountName+".file.core.windows.net/fileShare/fileName";
    /**
     * please note the date formate should be  ISO 8601 UTC formats 
     * for further information, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/formatting-datetime-values
    */
    String start = "startTime";
    String expiry = "expiry";
    String apiVersion = "2019-12-12";

    String stringToSign = accountName + "\n" +
                "r\n" +
                "f\n" +
                "o\n" +
                start + "\n" +
                expiry + "\n" +
                "\n" +
                "https\n" +
                apiVersion +"\n";

    String signature = getHMAC256(key, stringToSign);

    try

        String sasToken = "sv=" + azureApiVersion +
            "&ss=f" +
            "&srt=o" +
            "&sp=r" +
            "&se=" +URLEncoder.encode(expiry, "UTF-8") +
            "&st=" + URLEncoder.encode(start, "UTF-8") +
            "&spr=https" +
            "&sig=" + URLEncoder.encode(signature, "UTF-8");

    System.out.println(resourceUrl+"?"+sasToken);

     catch (UnsupportedEncodingException e) 
        e.printStackTrace();
    


private static String getHMAC256(String accountKey, String signStr) 
    String signature = null;
    try 
        SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(accountKey), "HmacSHA256");
        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        sha256HMAC.init(secretKey);
        signature = Base64.getEncoder().encodeToString(sha256HMAC.doFinal(signStr.getBytes("UTF-8")));
     catch (Exception e) 
        e.printStackTrace();
    
    return signature;

【讨论】:

谢谢吉姆,我非常感谢你。我指的是“创建服务 sas”,但正确的文档是“创建帐户 sas”。非常感谢您帮助我。

以上是关于Azure 文件共享 SAS 令牌签名未按预期生成,如何为文件对象生成签名以匹配门户中生成的签名?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Azure Blob 存储中的文件夹生成共享访问签名?

Microsoft 文档在以编程方式生成 SAS 令牌时出现问题。错误:“签名字段格式不正确”

Azure CDN URL使用令牌身份验证和Blob存储SAS重写规则

尝试使用 SAS 访问 Azure blob 时收到“签名不匹配。使用的签名字符串是...”

有没有办法重新生成 Azure Blob 存储 SAS 令牌

Azure 存储帐户生成 SAS 令牌,而不是 SAS URI