从 Java 向 Azure API 应用程序进行身份验证

Authenticate to an Azure API App from Java

我有一个与此类似的问题 post:Authenticate to Azure API App using ADAL 但在我的情况下,我有一个客户在 JBoss 中托管了一个 Java 客户端,他需要访问我的 API。该服务被保护为 'Public (authenticated)',我从浏览器访问它没有任何问题。我知道我可以在 .net 中创建一个 Azure API 应用程序客户端,但我找不到任何关于如何从 Java 进行身份验证的示例。这目前是否可行?如果可行,有人有任何有用的示例或建议吗?

我查看了下面的一些文档,在 Java 中制作了一个示例,用于从经过 AAD 身份验证的客户端调用 Azure API 应用程序。

作为参考:

  1. https://azure.microsoft.com/en-us/documentation/articles/app-service-api-authentication-client-flow/
  2. https://azure.microsoft.com/en-us/documentation/articles/app-service-api-dotnet-add-authentication/
  3. https://azure.microsoft.com/en-us/documentation/articles/app-service-authentication-overview/

对于示例,我在 Eclipse 中创建了一个 maven 项目并使用了库 adal4jcommon-iohttpclient。下面是 pom.xml 文件中的依赖项配置。

<dependencies>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>adal4j</artifactId>
        <version>1.1.2</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.1</version>
    </dependency>
</dependencies>

服务安全示例代码为Public (authenticated),请注意代码注释

    String gateway_url = "https://<GatewayHost>.azurewebsites.net/";
    String app_id_uri = gateway_url + "login/aad";
    String authority = "https://login.microsoftonline.com/<aad-domain>.onmicrosoft.com";
    String clientId = "<clientId>";
    String clientSecret = "<key>";
    String url = "https://<ApiAppHost>.azurewebsites.net/...";
/*
 *  Get Access Token from Gateway Login URL with authentication provider name
 *  Note: Please refer to the aad sample in Java for Native Headless at https://github.com/Azure-Samples/active-directory-java-native-headless
 */
HttpsURLConnection conn = (HttpsURLConnection) new URL(app_id_uri).openConnection();
AuthenticationContext context = null;
    AuthenticationResult result = null;
    ExecutorService service = null;
    try {
        service = Executors.newFixedThreadPool(1);
        context = new AuthenticationContext(authority, false, service);
        ClientCredential credential = new ClientCredential(clientId, clientSecret);
        Future<AuthenticationResult> future = context.acquireToken(app_id_uri, credential, null);
        result = future.get();
    } finally {
        service.shutdown();
    }
    String accessToken = null;
    if (result == null) {
        throw new ServiceUnavailableException(
                "authentication result was null");
    } else {
        accessToken = result.getAccessToken();
        System.out.println("Access Token: " +accessToken);
    }
    /*
     * Using access token to get authentication token
     */
    String data = "{\"access_token\": \""+accessToken+"\"}";
    conn.setRequestMethod("POST");
    conn.setDoOutput(true);
    conn.addRequestProperty("Content-Length", data.length()+"");
    new DataOutputStream(conn.getOutputStream()).writeBytes(data);
    String authTokenResp = IOUtils.toString(conn.getInputStream());
    System.out.println("Get Authentication Token Response: " + authTokenResp);
    /*
     * The content of Authentication Token Response is as {"user": {"userId": "sid:xxx...xxx"}, "authenticationToken": "xxxx...xxxxx"}.
     * Need to extract the authenticationToken from Json.
     */
    Gson gson = new Gson();
    Map<String, Object> map = gson.fromJson(authTokenResp, Map.class);
    String authenticationToken = (String) map.get("authenticationToken");
    System.out.println("Authentication Token: "+authenticationToken);
    /*
     * Using authentication token as X-ZUMO-AUTH header to get data from Api App
     * Note: Must using Apache Common HttpClient supported HTTP 30x redirection, Class Http(s)URLConnection not support.
     *          There are three times continuous 302 redirection in accessing Api App with zumo token. 
     */
    HttpGet httpGet = new HttpGet(url);
    httpGet.addHeader("x-zumo-auth", authenticationToken);
    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpResponse resp = httpclient.execute(httpGet);
    String apiAppData = IOUtils.toString(resp.getEntity().getContent());
    System.out.println(apiAppData);

如有任何疑问,请随时告诉我。

try (CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(getSslConnectionSocketFactory(logger))
                .build();
             CloseableHttpResponse response = httpClient.execute(httpPost)) {

             final int httpStatusCode = response.getStatusLine().getStatusCode();
            
        } catch (IOException ex) {
            logger.info(format("Error relaying to court store %s , %s", caseReference, ex));
           
 }


    private SSLConnectionSocketFactory getSslConnectionSocketFactory(final Logger logger) {
        SSLConnectionSocketFactory sslConSocFactory = null;
        try {
            final KeyStore ks = KeyStore.getInstance("Windows-MY");
            ks.load(null, null);
            final Certificate certificate = ks.getCertificate(CERTIFICATE_SUBJECT);
            if (certificate == null) {
                logger.info(format("Certificate not found for %s", CERTIFICATE_SUBJECT));
            }
            final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
            final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(ks, acceptingTrustStrategy).build();
            sslConSocFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | KeyManagementException ex) {
            logger.info(format("Error reading certificate : , %s", ex));
        }
        return sslConSocFactory;
    }