java.lang.IllegalArgumentException:除非ServiceClient使用帐户密钥凭证,否则无法创建共享访问签名 [英] java.lang.IllegalArgumentException: Cannot create Shared Access Signature unless the Account Key credentials are used by the ServiceClient

查看:612
本文介绍了java.lang.IllegalArgumentException:除非ServiceClient使用帐户密钥凭证,否则无法创建共享访问签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用MSI访问Azure Blob存储容器以生成共享访问签名.但是每次我尝试访问时,都会出现以下错误:

I am trying to use MSI to access Azure Blob Storage containers to generate shared access signature. But every time i am trying to access , i am getting following error:

`java.lang.IllegalArgumentException: Cannot create Shared Access Signature unless the Account Key credentials are used by the ServiceClient.` 

我不想使用凭据或AAD访问Blob存储容器.只想使用MSI,因为这是我们要在应用程序中适应访问Azure资源的独特模式.我想念的是什么东西.我在Splunk日志中检查了MSI令牌已成功生成.以下是我创建CloudBlobClient来访问Blob容器的方式:

I dont want to access blob storage container using credentials or AAD. Just want to use MSI, as this is the unique mode that we want to adapt in our application to access Azure resources. What this thing i am missing. I checked in my Splunk logs that MSI token is generating successfully. Below is the way i am creating the CloudBlobClient to access Blob container:

public CloudBlobClient cloudBlobClient() throws URISyntaxException {
    String storageAccountName = propertyUtil.getStorageAccountName();
    // Implemented some logic in AzureStorageMSICredential class to fetch access 
    // token, and its working correctly
    String msiToken = azureStorageMSICredentials.getToken();
    LOG.info("Initiating CloudBlobClient.... msitoken = " + msiToken);
    StorageCredentials storageCredentials =
      new StorageCredentialsToken(storageAccountName, msiToken);

    URI storageAccountURI = URIUtils.getStorageAccountURI(storageAccountName);
    CloudBlobClient cloudBlobClient = new CloudBlobClient(storageAccountURI, 
      storageCredentials);
    return cloudBlobClient;
  }

我在stackoverflow上搜索了许多线程,这似乎是其中之一的重复,但并非如此.有些是2017年的.

I searched many threads on stackoverflow, which seems dupliate of this one, but not really. Some are of 2017.

推荐答案

通过查看Azure Storage Java SDK,我发现generateSharedAccessSignature方法将最终调用以下内容:

By reviewing the Azure Storage Java SDK, I find that the generateSharedAccessSignature method will finally call the following:

public String generateSharedAccessSignature(
        final SharedAccessBlobPolicy policy, final SharedAccessBlobHeaders headers,
        final String groupPolicyIdentifier, final IPRange ipRange, final SharedAccessProtocols protocols)
        throws InvalidKeyException, StorageException {

    if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
        throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
    }

    final String resourceName = this.getCanonicalName(true);

    final String signature = SharedAccessSignatureHelper.generateSharedAccessSignatureHashForBlobAndFile(
            policy, headers, groupPolicyIdentifier, resourceName, ipRange, protocols, this.blobServiceClient,
            this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
            this.getSnapshotID());

    final UriQueryBuilder builder = SharedAccessSignatureHelper.generateSharedAccessSignatureForBlobAndFile(
            policy, headers, groupPolicyIdentifier,
            this.isSnapshot() ? Constants.QueryConstants.BLOB_SNAPSHOT_SERVICE : Constants.QueryConstants.BLOB_RESOURCE,
            ipRange, protocols, signature);

    return builder.toString();
}

签名字符串是Hmac256字符串. StorageCredentialsHelper中有一种方法可以对其进行计算.

The signature string is a Hmac256 string. There is a method in StorageCredentialsHelper to compute it.

public static synchronized String computeHmac256(final StorageCredentials creds, final String value) throws InvalidKeyException {
    if (creds.getClass().equals(StorageCredentialsAccountAndKey.class)) {
        byte[] utf8Bytes = null;
        try {
            utf8Bytes = value.getBytes(Constants.UTF8_CHARSET);
        }
        catch (final UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
        return Base64.encode(((StorageCredentialsAccountAndKey) creds).getHmac256().doFinal(utf8Bytes));
    }
    else {
        return null;
    }
}

在此方法中,需要StorageCredentialsAccountAndKey.它是可用于签名数据的密钥.但是,当您使用MSI进行身份验证时,您使用的令牌实际上是一个AAD访问令牌,该令牌不能用于在该位置进行签名.您可以使用以下代码进行检查:

In this method, a StorageCredentialsAccountAndKey is required. It is a key which can be used to sign data. However, as you were using MSI as authentication, the token you used was actually an AAD access token which cannot be used to sign in this place. You can check that with the following code:

StorageCredentials credentials = blobClient.getCredentials();
System.out.println(credentials.toString(true));

因此,在generateSharedAccessSignature方法中,将引发错误:

So, in the generateSharedAccessSignature method, an error will be thrown:

    if (!StorageCredentialsHelper.canCredentialsSignRequest(this.blobServiceClient.getCredentials())) {
        throw new IllegalArgumentException(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY);
    }

最后,如果当前使用MSI作为身份验证,则无法生成SharedAccessSignature.您可以将请求发布到 Azure存储用户语音.如果您的请求被否决,则开发人员团队可以添加此功能.

In conclusion, you are not able to generate SharedAccessSignature if you use MSI as authentication currently. You may post your request to the Azure Storage User Voice. If your request is voted high, the developer team may add this feature.

这篇关于java.lang.IllegalArgumentException:除非ServiceClient使用帐户密钥凭证,否则无法创建共享访问签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆