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?

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

下面是我通过 Azure Portal 生成的 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

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

使用的key是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 令牌以进行文件对象访问。

如果要创建sas token 来访问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;
}