Azure RateCard“ AuthenticationFailed”

时间:2019-03-07 11:50:55

标签: java eclipse azure api

我想通过带有Java应用程序的Billing Api获得Azure RateCard。 首先,我创建一个AccessToken,它可以正常工作。但是,当我想使用此AccessToken来获取RateCard时,会收到身份验证错误。 这是我的Java代码:

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 TestingAzure {

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 = "*****";
    String clientId = "*****";
    String clientSecret = "*****";
    clientSecret=java.net.URLEncoder.encode(clientSecret,"UTF-8");
    System.out.println(clientSecret);
    String accessToken = getAccessToken(tenantId, clientId, clientSecret);
    System.out.println(accessToken);
    String subscriptionId = "*****";
    String apiVersion = "2015-06-01-preview";
    String offerId = "****";
    String currency = "EUR";
    String locale = "de-DE";
    String region = "DE";
    String rateCardResp = getRateCard(subscriptionId, apiVersion, offerId, currency, locale, region, accessToken);
    System.out.println(rateCardResp);
}

}

在Eclipse中,错误是:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://management.azure.com/subscriptions/*subscriptionID*/providers/Microsoft.Commerce/RateCard?api-version=2015-06-01-preview&$filter=OfferDurableId%20eq%20'MS-AZR-0017P'%20and%20Currency%20eq%20'EUR'%20and%20Locale%20eq%20'de-DE'%20and%20RegionInfo%20eq%20'DE'
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.TestingAzure.getRateCard(TestingAzure.java:60)
at com.nttdata.altemista.TestingAzure.main(TestingAzure.java:84)

当我搜索URL时,出现以下消息:

{"error":{"code":"AuthenticationFailed","message":"Fehler bei der Authentifizierung. Der Authorization-Header fehlt."}}

实际上,在此订阅中,我扮演最高的角色。我不知道我能尝试什么。

1 个答案:

答案 0 :(得分:0)

在示例中,您是否已对服务主体给予足够的权限,即访问Windows Azure服务管理API的权限。

这是一个很好的示例,如果要访问Java中的管理资源,如何在Azure AD中配置应用程序

https://blogs.msdn.microsoft.com/azureossds/2015/06/23/authenticating-azure-resource-management-rest-api-requests-using-java/

或者,这是配置本地应用程序以使用Azure价目表Api的方法 步骤1:在AAD租户中配置本机客户端应用程序

在运行示例应用程序之前,您需要允许其访问AAD租户,以进行身份​​验证和授权,以访问Billing API。如果已经配置了要使用的本机客户端应用程序(并且已按照以下步骤进行配置),则可以跳到步骤2。

要配置新的AAD应用程序,请执行以下操作:

  1. 使用已被授予信任该AAD租户的订阅上的服务管理员/共同管理员访问权限并已授予AAD租户中的全局管理员访问权限的凭据登录到Azure门户。有关管理服务管理员和共同管理员的详细信息,请参见Manage Accounts, Subscriptions, and Administrative Roles

  2. 选择您要使用的AAD租户,然后转到“应用程序”页面。

  3. 从那里,您可以使用“添加”功能来“添加组织正在开发的新应用程序”。

  4. 为新应用程序提供名称(即ConsoleApp-Billing-RateCard或类似名称)。

  5. 确保选择“本机客户端应用程序”类型,然后为“重定向URI”指定有效的URL(对于本示例而言,可以为http://localhost/),然后单击复选标记保存。

  6. 添加新应用程序后,在应用程序列表中再次选择它,然后单击“配置”,以确保示例应用程序将有权访问Windows Azure服务管理API。用于保护Billing API的权限。

  7. 向下滚动到新创建的应用程序的配置页面的“其他应用程序的权限”部分。然后单击“添加应用程序”按钮,选择“ Windows Azure服务管理”行,然后单击复选标记进行保存。保存后,将鼠标悬停在“ Windows Azure服务管理”行右侧的“委派权限”区域,单击“委派权限”下拉列表,选择“访问Azure服务管理(预览)”选项,然后单击“再次保存”。

注意:默认情况下,已启用“ Windows Azure Active Directory”权限“启用登录并读取用户的配置文件”。它允许用户使用其组织帐户登录该应用程序,从而使该应用程序能够读取已登录用户的配置文件,例如其电子邮件地址和联系信息。这是委派权限,使用户能够在继续之前同意。有关配置Azure AD租户以使应用程序能够访问您的租户的更多深度,请参考Adding, Updating, and Removing an Application

  1. 当您在此页面上时,还请注意/复制“客户端ID” GUID和“重定向URI”,

,因为您将在下面的步骤3中使用它们。您还将需要您的Azure订阅ID和AAD租户域名,您都可以从管理门户中的“设置”页面复制这两者。

注意:-如果要使用grant_type =“ Client_credential”并使用客户端ID和client_secret,请确保您在订阅中至少具有admin / co admin角色,并且您的应用程序具有足够的权限如上所述。