Как получить доступ к контейнеру Azure WASB на основе токена SAS в Java? - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь использовать ключ SAS для получения контейнера из Azure WASB в коде Java.Это делается в коде HDFS, но по какой-то причине я не могу заставить его работать.Мне удалось упростить его до приложения ниже, которое также не работает.Я думаю, что это либо проблема с тем, как мы генерируем токен SAS, либо разрешения для учетной записи Azure.Может кто-то взглянуть на это и указать мне в правильном направлении, что может быть проблема?Спасибо!

public static void main(String[] arguments)
{
    try {
        String storage_account = "wasbvalidation";
        String container = "demoengagement1";
        CloudBlobClient blobClient = getBlobClient(storage_account);

        CloudBlobContainer blobContainer = blobClient.getContainerReference(container);

        blobContainer.downloadAttributes(); // This call succeeds

        SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy();
        policy.setPermissions(EnumSet.allOf(SharedAccessBlobPermissions.class));
        policy.setSharedAccessStartTime(Date.valueOf(LocalDate.now().minusYears(2)));
        policy.setSharedAccessExpiryTime(Date.valueOf(LocalDate.now().plusYears(2)));

        String sas = blobContainer.getUri().toString() + "?" + blobContainer.generateSharedAccessSignature(policy, null, null, SharedAccessProtocols.HTTPS_ONLY);

        // Code after this point is emulating what HDFS is doing, so I'd rather not change it.
        URI blobUri = new URI(blobContainer.getUri().toString());
        StorageCredentials credentials = new StorageCredentialsSharedAccessSignature(sas);
        CloudBlobContainer sasContainer = new CloudBlobContainer(blobUri, credentials);
        sasContainer.downloadAttributes(); // This call fails, however.
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static CloudBlobClient getBlobClient(String storageAccount) throws NullPointerException {
    String storageConnectionString = "DefaultEndpointsProtocol=https;" + "AccountName=" + storageAccount + ";" + "AccountKey=" + accountKey;
    CloudStorageAccount csa = null;
    try {
        csa = CloudStorageAccount.parse(storageConnectionString);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    CloudBlobClient blobClient = csa.createCloudBlobClient();
    return blobClient;
}

1 Ответ

0 голосов
/ 31 января 2019

В соответствии с вашим кодом, я думаю, вы хотите получить свойства и метаданные контейнера больших двоичных объектов, создав URL-адрес с помощью SAS для контейнера.Однако строка SAS, сгенерированная SharedAccessBlobPolicy, похожа на sig=1G7tiQnLEtbjk2RSNuUSKH7gLNVZjqhuLQL%2Fci%2FXS50%3D&st=2017-01-30T16%3A00%3A00Z&se=2021-01-30T16%3A00%3A00Z&sv=2018-03-28&sp=racwdl&sr=b для большого двоичного объекта (sr=b), а не для контейнера (sr=c, например st=2019-01-31T08%3A38%3A46Z&se=2019-02-01T08%3A38%3A46Z&sp=rl&sv=2018-03-28&sr=c&sig=KnynNYBUtzNSYtBEcYakMrhAXPRIk60wztB3BFv5b%2Bs%3D, скопированного из обозревателя хранилища Azure).

Iпытался использовать CloudStorageAccount с SharedAccessAccountPolicy для создания учетной записи SAS для блоба с помощью приведенного ниже кода, но он все еще не работает.

учетной записи SAS .Учетная запись SAS делегирует доступ к ресурсам в одной или нескольких службах хранения.Все операции, доступные через службу SAS, также доступны через учетную запись SAS.Кроме того, с помощью учетной записи SAS вы можете делегировать доступ к операциям, которые применяются к данной службе, например, «Получить / установить свойства службы» и «Получить статистику службы».Вы также можете делегировать доступ к операциям чтения, записи и удаления для контейнеров BLOB-объектов, таблиц, очередей и общих файловых ресурсов, которые не разрешены для службы SAS.См. Создание аккаунта SAS для получения более подробной информации о создании токена SAS аккаунта.

SharedAccessAccountPolicy accountPolicy = new SharedAccessAccountPolicy();
accountPolicy.setPermissions(EnumSet.allOf(SharedAccessAccountPermissions.class));
accountPolicy.setSharedAccessStartTime(Date.valueOf(LocalDate.now().minusYears(2)));
accountPolicy.setSharedAccessExpiryTime(Date.valueOf(LocalDate.now().plusYears(2)));

String sas = csa.generateSharedAccessSignature(accountPolicy);

Я тестирую приведенный ниже код,

StorageCredentials credentials = new StorageCredentialsSharedAccessSignature(sas);
CloudBlobContainer sasContainer = new CloudBlobContainer(new URI(container2.getUri().toString()+"?"+sas), credentials);
sasContainer.downloadAttributes();

Затем, чтобы получить исключение.

Exception in thread "main" java.lang.IllegalArgumentException: Cannot provide credentials as part of the address and as constructor parameter. Either pass in the address or use a different constructor.

Или для проверки кода CloudBlobContainer sasContainer = new CloudBlobContainer(new URI(container2.getUri().toString()+"?"+sas)), чтобы получить исключение.

Exception in thread "main" com.microsoft.azure.storage.StorageException: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

Кажется, это вызвано реализацией Azure Java Storage SDK v8.0.0 после того, как я исследовалисходные коды SDK.Возможно, вы можете сообщить об этом Microsoft, чтобы попросить решить эту проблему.

Я попытался сгенерировать URL-адрес контейнера с помощью SAS, используя Azure Java Storage SDK v10, с помощью приведенного ниже кода, он работает нормально.

Maven-зависимость для v10:

<!-- https://mvnrepository.com/artifact/com.microsoft.azure/azure-storage-blob -->
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-storage-blob</artifactId>
    <version>10.4.0</version>
</dependency>

Код для генерации URL-адреса контейнера с SAS:

String accountName = "<your account name>";
String accountKey = "<your account key>";
SharedKeyCredentials credentials = new SharedKeyCredentials(accountName, accountKey);
final ServiceURL serviceURL = new ServiceURL(new URL("http://" + accountName + ".blob.core.windows.net"), StorageURL.createPipeline(credentials, new PipelineOptions()));
String containerName = "<container name>";
ServiceSASSignatureValues values = new ServiceSASSignatureValues()
                .withProtocol(SASProtocol.HTTPS_ONLY) // Users MUST use HTTPS (not HTTP).
                .withExpiryTime(OffsetDateTime.now().plusDays(2)) // 2 days before expiration.
                .withContainerName(containerName)
                .withBlobName(blobName);
ContainerSASPermission permission = new ContainerSASPermission()
                .withRead(true)
                .withAdd(true)
                .withWrite(true);
values.withPermissions(permission.toString());
SASQueryParameters serviceParams = values.generateSASQueryParameters(credentials);
String sas = serviceParams.encode();

String containerUrlWithSAS = String.format(Locale.ROOT, "https://%s.blob.core.windows.net/%s%s",
                accountName, containerName, sas);
HttpPipeline pipeline = new HttpPipelineBuilder().build();
ContainerURL sasContainer = new ContainerURL(new URL(containerUrlWithSAS), pipeline);
sasContainer.getProperties();

Примечание: функция getProperties из ContainerURL в SDK v10 аналогично downloadAttributes из CloudBlobContainer в SDK v8, который также возвращает метаданные контейнера и системные свойства.

...