英文:
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());
}
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());
Analyze access token via the link
So if you want to use sharekey to call the api, please create a new httoclient.
答案2
得分: 0
我看到您想要使用 Azure 中已注册应用程序的凭据。因此,您可能希望通过 使用 Azure Active Directory 授权访问 Blob 和队列。
- 您需要授予您的应用程序访问存储账户的权限
为了能够读取您的存储账户,您至少需要添加 Storage Blob Data Reader
角色。
- 在您的代码中获取令牌,并使用该令牌访问您的存储账户:
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
英文:
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
- You need to grant your application access to your storage account
To be able to read your storage account, you need to at least add Storage Blob Data Reader
role.
- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论