Я хочу получить ответ Azure RateCard Json через Billing REST API. Для этого я использую следующий код в eclipse:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class RateCardRest {
public static String getAccessToken(String tenantId, String clientId, String clientSecret)
throws MalformedURLException, IOException {
String endpoint = String.format("https://login.microsoftonline.com/%s/oauth2/token", tenantId);
String postBody = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=%s",
clientId, clientSecret, "https://management.azure.com/");
HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
conn.setRequestMethod("POST");
conn.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setDoOutput(true);
conn.getOutputStream().write(postBody.getBytes());
conn.connect();
// If you want to see the response content, please use the commented code below.
// BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// StringBuilder builder = new StringBuilder();
// String line = null;
// while ((line = reader.readLine()) != null) {
// builder.append(line);
// }
// reader.close();
// System.out.println(builder.toString());
// The output for access token is {"token_type":"Bearer","expires_in":"3600","ext_expires_in":"3600","expires_on":"1550660092","not_before":"1550656192","resource":"https://management.azure.com/","access_token":"eyJ0eXAiOiJKV1QiL...."}
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(conn.getInputStream());
String accessToken = null;
while (parser.nextToken() != JsonToken.END_OBJECT) {
String name = parser.getCurrentName();
if ("access_token".equals(name)) {
parser.nextToken();
accessToken = parser.getText();
}
}
return accessToken;
}
public static String getRateCard(String subscriptionId, String apiVersion, String offerId, String currency,
String locale, String region, String accessToken) throws MalformedURLException, IOException {
String endpoint = String.format(
"https://management.azure.com/subscriptions/%s/providers/Microsoft.Commerce/RateCard?api-version=%s&$filter=OfferDurableId eq '%s' and Currency eq '%s' and Locale eq '%s' and RegionInfo eq '%s'",
subscriptionId, apiVersion, offerId, currency, locale, region).replaceAll(" ", "%20");
HttpURLConnection conn = (HttpURLConnection) new URL(endpoint).openConnection();
conn.setRequestMethod("GET");
conn.addRequestProperty("Authorization", "Bearer " + accessToken);
conn.addRequestProperty("Content-Type", "application/json");
conn.connect();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
reader.close();
return builder.toString();
}
public static void main(String[] args) throws MalformedURLException, IOException {
String tenantId = "<your tenant id like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx";
String clientId = "<your client id registed in AAD like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx";
String clientSecret = "<your client secret key generated in AAD>";
String accessToken = getAccessToken(tenantId, clientId, clientSecret);
System.out.println(accessToken);
String subscriptionId = "<your subscription id like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx";
String apiVersion = "2015-06-01-preview";
String offerId = "<your offer id like XX-AZR-XXXXX";
String currency = "USD";
String locale = "en-US";
String region = "US";
String rateCardResp = getRateCard(subscriptionId, apiVersion, offerId, currency, locale, region, accessToken);
System.out.println(rateCardResp);
}
}
Это вызывает следующую ошибку:
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 401 for URL: https://login.microsoftonline.com/"myTenantID"/oauth2/token
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.nttdata.altemista.RateCardRest.getAccessToken(RateCardRest.java:38)
at com.nttdata.altemista.RateCardRest.main(RateCardRest.java:74)
Когда я ищу URL-адрес, я получаю следующее сообщение:
AADSTS900561: The endpoint only accepts POST, OPTIONS requests. Received a GET request.
Извините, что вы имеете в виду под телом ответа?
Данные, которые вы получаете от conn.getInputStream()
401 означает, что вы не авторизованы, поэтому токен, который вы получаете, недействителен. Вы делаете что-то не так с запросом getAccessToken. В большинстве случаев поле resource как-то неправильно, к какому ресурсу вы пытаетесь получить доступ?
Как я могу получить данные из conn.getInputStream(), потому что я не могу вывести «String»? Где у меня есть поле ресурсов? Извините, что задаю так много вопросов, но этот код не от меня.
@juunas означает resource, что вы получаете токен для просмотра строки кода, которую я помечаю знаком ??. Обычно пользователь часто делает здесь ошибку: String postBody = String.format("grant_type=client_credentials&client_id=%s&client_secret=%s&resource=%???????????????? ???????", clientId, clientSecret, "management.azure.com/");
@Wuld Если вы хотите вывести данные conn.getInputStream(), вы можете использовать код, который я комментирую.
@Wuld У меня есть вопрос о том, какую Azure вы использовали? Global Azure, German Azure, даже China Azure? Они отличаются для кода, использующего разные конечные точки Azure.
@PeterPan К сожалению, не потому, что тогда я получаю ошибку в строке 28 от BufferedReader.
@PeterPan Я предполагаю, что Azure в Германии, потому что мы немецкая компания. Могу я посмотреть это где-нибудь?
@Wuld Кроме Global Azure, я ничего не знаю о German Azure. Причина, по которой вы спрашиваете, какой Azure вы использовали, просто я давно ответил на вопрос о China Azure.
@ALFA, как я могу изменить поле ресурса?
@Wuld Следите за разделом Request URI, вы также можете использовать https://management.core.windows.net/ в качестве ресурса здесь.
@Wuld Я предлагаю вам использовать почтальона для отправки того же запроса на получение токена доступа, чтобы увидеть тело ответа о деталях ошибки.
Та же ошибка с https://management.core.windows.net/
@Wuld Используя https://management.core.windows.net/, у меня это тоже работает. Пожалуйста, используйте Postman, чтобы попытаться получить токен доступа, чтобы увидеть тело ответа. Вот моя примерная фигура i.stack.imgur.com/42exG.png.
@PeterPan теперь работает. Я получаю AccessToken. При получении групп ресурсов я получаю следующую ошибку: { "error": { "code": "AuthorizationFailed", "message": "The client /*...*/ with object id /*....*/ does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/read' over scope '/subscriptions//*....*/'." } } Значит ли это, что у меня недостаточно прав для этой подписки?




Вам нужно UrlEncode ваш секретный ключ клиента, сгенерированный в AAD.
clientSecret=java.net.URLEncoder.encode(clientSecret,"UTF-8");
ниже к
String clientSecret = "<your client secret key generated in AAD>";
Спасибо! Теперь getAccesToken возвращает AccessToken. Новая ошибка: Server returned HTTP response code: 403 for URL: /*....*/ URL дает сообщение. Заголовок авторизации отсутствует
Можете ли вы создать новый вопрос с более подробной информацией? Пожалуйста, добавьте детали сообщения об ошибке.
Вы проверили тело ответа? Обычно приводится подробная ошибка.