受众验证失败,在列出应用注册的 Azure 存储账户容器时。

huangapple go评论74阅读模式
英文:

Audience validation failed while listing azure storage account containers from app registrations

问题

以下是您提供的代码翻译后的内容:

尝试通过Azure注册应用程序的凭据从REST API获取Azure存储帐户容器的详细信息我已经构建了身份验证标头参数但在调用REST API时遇到了错误错误消息为受众验证失败受众不匹配”。

这是我的代码

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);
    }
}

这是您提供的认证签名字符串:

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;

希望这对您有所帮助。如果您还有其他问题,请随时问我。

英文:

I am trying to get the details of azure storage account containers from rest API using the credentials of a an registered application in azure. I have built the authentication header parameter and when I am calling the rest API I get this error which says Audience validation failed. Audience did not match.

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"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:deb7a983-401e-008d-30e7-0c884e000000
Time:2020-04-07T14:17:14.0081901Z</Message><AuthenticationErrorDetail>Audience validation failed. Audience did not match.</AuthenticationErrorDetail></Error>
19:47:16.828 [main] INFO - <-- END HTTP

This is my 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);
}
}

This is the authsignstring

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

I have tried this as well:

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");

and

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

Can you help me with this? I am stuck here from a long time.
I want the JSON response for the list of containers.

答案1

得分: 1

以下是已翻译的内容:

如果您想要使用SharedKeyLite授权调用Azure Blob REST API,请参考以下代码:

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());
}

在使用RestClient调用Azure REST API时,它将使用Azure AD访问令牌进行授权。但是,RestClient使用错误的资源来获取Azure AD访问令牌。它使用https://management.core.windows.net/,但我们需要https:\\storage.azure.com\

我的测试代码:

OkHttpClient httpClient = restClient.httpClient().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();
okhttp3.Response response1 = httpClient.newCall(request).execute();
System.out.println(response1.body().string());

通过以下链接分析访问令牌:https://jwt.ms。如果您想要使用SharedKey调用API,请创建一个新的HttpClient。

英文:

If you want to use SharedKeyLite auth to call Azur blob rest api, please refer to the following code

 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());
}

受众验证失败,在列出应用注册的 Azure 存储账户容器时。


Update

When we use RestClient to call the Azure rest api, it will use Azure AD access token to do auth. But the restclient use wrong resource to get Azure AD access token. It uses https://management.core.windows.net/ but we needs https:\\storage.azure.com\

My test code

 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());

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

Analyze access token via the link
受众验证失败,在列出应用注册的 Azure 存储账户容器时。

So if you want to use sharekey to call the api, please create a new httoclient.

答案2

得分: 0

我看到您想要使用 Azure 中已注册应用程序的凭据。因此,您可能希望通过 使用 Azure Active Directory 授权访问 Blob 和队列

  1. 您需要授予您的应用程序访问存储账户的权限

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

为了能够读取您的存储账户,您至少需要添加 Storage Blob Data Reader 角色。

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

  1. 在您的代码中获取令牌,并使用该令牌访问您的存储账户:
    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());
        }
    }

Output

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

英文:

I see that you want to use the credentials of a registered application in azure. So, you may want to Authorize access to blobs and queues using Azure Active Directory

  1. You need to grant your application access to your storage account

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

To be able to read your storage account, you need to at least add Storage Blob Data Reader role.

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

  1. Acquire a token in your code, and use the token to access your storage account:
    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());
}
}

Output

受众验证失败,在列出应用注册的 Azure 存储账户容器时。

huangapple
  • 本文由 发表于 2020年4月7日 22:51:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/61082869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定