Ошибка проверки аудитории при перечислении azure контейнеров учетной записи хранения из регистраций приложений - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь получить подробную информацию о azure контейнерах учетной записи хранения из rest API, используя учетные данные зарегистрированного приложения в azure. Я построил параметр заголовка аутентификации, и когда я вызываю API остальных, я получаю эту ошибку, которая говорит Проверка аудитории не удалась. Аудитория не совпадает.

19:47:16.826 [main] INFO - <-- 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. https://shagundonotdeleteaccount.blob.core.windows.net/?comp=list (288 ms, 426-byte body) 19:47:16.828 [main] INFO - 426-byte body: ?<?xml version="1.0" encoding="utf-8"?>AuthenticationFailed Серверу не удалось аутентифицировать запрос. Убедитесь, что значение заголовка авторизации сформировано правильно, включая подпись. RequestId: deb7a983-401e-008d-30e7-0c884e000000 Время: 2020-04-07T14: 17: 14.0081901Z Ошибка проверки аудитории. Аудитория не соответствует. 19: 47: 16,828 [главная] ИНФОРМАЦИЯ - <- КОНЕЦ HTTP </code>

Это мой код:

        ApplicationTokenCredentials credentials = new ApplicationTokenCredentials("clientID",
                "domain", "secret", AzureEnvironment.AZURE);
RestClient restClient = new RestClient.Builder()
                .withBaseUrl(AzureEnvironment.AZURE, AzureEnvironment.Endpoint.RESOURCE_MANAGER)
                .withSerializerAdapter(new AzureJacksonAdapter())
                .withReadTimeout(150, TimeUnit.SECONDS)
                .withLogLevel(LogLevel.BODY)
                .withResponseBuilderFactory(new AzureResponseBuilder.Factory())
                .withCredentials(credentials).build();
   Azure azure = Azure.authenticate(restClient, credentials.domain()).withDefaultSubscription();
             Base64 base64 = new Base64();

  for (StorageAccount account : azure.storageAccounts().list()) {

            URL url = new URL("https://" + account.name() + ".blob.core.windows.net/?comp=list");
            StorageAccountKey key = account.getKeys().get(0);
            SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
            fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
            String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";

            StringBuilder sb = new StringBuilder();
            sb.append("GET\n"); // method
            sb.append('\n'); // md5 (optional)
            sb.append('\n'); // content type
            sb.append('\n'); // legacy date
            sb.append("x-ms-date:" + date + '\n'); // headers
            sb.append("x-ms-version:2017-11-09\n");
            sb.append("/" + account.name() + url.getPath() + "?comp=list");

            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(base64.decode(key.value()), "HmacSHA256"));

            String authKey = new String(base64.encode(mac.doFinal(sb.toString().getBytes("UTF-8"))));
            String auth = "SharedKeyLite " + account.name() + ":" + authKey;
         OkHttpClient httpClient = restClient.httpClient();
         Request request = new Request.Builder()
                    .url(url)
                    //                    .addHeader("content-type", "application/json")
                    //                    .addHeader("cache-control", "no-cache")
                    .addHeader("x-ms-version", "2017-11-09")
                    .addHeader("x-ms-date", date)
                    .addHeader("Authorization", auth)
                    .get()
                    .build();

            okhttp3.Response response = httpClient.newCall(request).execute();
            httpClient.newCall(request);

            if (!response.isSuccessful()) {
                throw new RuntimeException("Request Failed" + response.code() + "\n" + response.message());
            }
            JSONParser parser = new JSONParser();
            String apiResponse = response.body().string();

            if (apiResponse != null) {
                org.json.simple.JSONObject responseJSON = (org.json.simple.JSONObject) parser.parse(apiResponse);
                System.out.println(responseJSON);

            }

        }

Это это authsignstring

GET



x-ms-date:Tue, 07 Apr 2020 14:17:13 GMT
x-ms-version:2017-11-09
/mystorageaccount/?comp=list

Я тоже пробовал это:

StringBuilder sb = new StringBuilder();
        sb.append("GET\n"); // method
        sb.append('\n'); // content encoding
        sb.append('\n'); // content language
        sb.append('\n'); // content length
        sb.append('\n'); // md5 (optional)
        sb.append('\n'); // content type
        sb.append('\n'); // legacy date
        sb.append('\n'); // if-modified-since
        sb.append('\n'); // if-match
        sb.append('\n'); // if-none-match
        sb.append('\n'); // if-unmodified-since
        sb.append('\n'); // range
        sb.append("x-ms-date:" + date + '\n'); // headers
        sb.append("x-ms-version:2017-11-09\n");

        sb.append("/" + account.name() + "/" + "\ncomp:list");

и

String auth = "SharedKey " + account.name() + ":" + authKey;

Можете ли вы помочь мне с этим? Я застрял здесь на долгое время. Я хочу получить ответ JSON для списка контейнеров.

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Я вижу, что вы хотите использовать учетные данные зарегистрированного приложения в azure. Итак, вы можете Авторизовать доступ к BLOB-объектам и очередям, используя Azure Active Directory

  1. . Вам необходимо предоставить приложению доступ к учетной записи хранения
.

enter image description here

Чтобы прочитать вашу учетную запись хранения, вам нужно как минимум добавить Storage Blob Data Reader роль.

enter image description here

Получите токен в своем коде и используйте токен для доступа к вашей учетной записи хранения:
    public static void main(String[] args) throws IOException {
        String clientId = "your application id here";
        String clientSecret = "application secret here";
        String tenantId = "your tenant id";
        String storageResource = "https://storage.azure.com/";
        String url = "https://{your_storage_account_name}.core.windows.net/?comp=list";

        ApplicationTokenCredentials credentials = new ApplicationTokenCredentials(clientId,
                tenantId, clientSecret, AzureEnvironment.AZURE);

        String token = credentials.getToken(storageResource);

        OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("x-ms-version", "2017-11-09")
                .addHeader("Authorization", "Bearer "+token)
                .build();
        Response response = client.newCall(request).execute();
        if(response.isSuccessful()){
            System.out.println(response.body().string());
        }
    }

Вывод

enter image description here

0 голосов
/ 08 апреля 2020

Если вы хотите использовать SharedKeyLite auth для вызова API оставшегося BLOB-объекта Azur, обратитесь к следующему коду

 String StorageAccountName = "blobstorage0516";
         String StorageAccountKey = "";
        URL url = new URL("https://" + StorageAccountName + ".blob.core.windows.net/?comp=list");
        SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
        fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";
        StringBuilder sb = new StringBuilder();
        sb.append("GET\n"); // method
        sb.append("\n") ;//Content-MD5
        sb.append("\n") ;//Content-Type
        sb.append("\n") ;//data
        sb.append("x-ms-date:" + date + '\n'); // headers
        sb.append("x-ms-version:2017-11-09\n");
        sb.append("/" + StorageAccountName + url.getPath() + "?comp=list");
 System.out.println(sb.toString()); // print stringtosign
SecretKeySpec secretKey = new SecretKeySpec(Base64.getDecoder().decode(StorageAccountKey), "HmacSHA256");
        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        sha256HMAC.init(secretKey);
        String authKey=Base64.getEncoder().encodeToString(sha256HMAC.doFinal(sb.toString().getBytes("UTF-8")));
        String auth = "SharedKeyLite " + StorageAccountName + ":" + authKey;
        System.out.println(auth);
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder()
                             .url(url)
                             .method("GET", null)
                             .addHeader("x-ms-version", "2017-11-09")
                             .addHeader("x-ms-date", date)
                             .addHeader("Authorization", auth)
                             .build();
        Response response = client.newCall(request).execute();
        if(response.isSuccessful()){

            System.out.println(response.body().string());
        }

enter image description here


Обновление

Когда мы используем RestClient для вызова Azure rest api, он будет использовать Azure AD токен доступа для аутентификации. Но оставшийся клиент использует неверный ресурс для получения Azure токена доступа AD . Он использует https://management.core.windows.net/, но нам нужно https:\\storage.azure.com\

Мой тестовый код

 OkHttpClient httpClient = restClient.httpClient().newBuilder().build();
        //OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder()
                .url(url)
                .method("GET", null)
                .addHeader("x-ms-version", "2017-11-09")
                //.addHeader("x-ms-date", date)
                .build();
        //Response response = client.newCall(request).execute();

        okhttp3.Response response1 = httpClient.newCall(request).execute();



            System.out.println(response1.body().string());

enter image description here

Анализировать токен доступа по ссылке enter image description here

Поэтому, если вы хотите использовать sharekey для вызова API, создайте новый httoclient.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...