我正在尝试访问图形api。我使用MSAL4J
来访问graph
api。但我得到com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: connect timed out
,即使我不使用我的vpn。
我遵循这个教程。我已经遵循了上面提到的所有步骤。
这里是堆栈跟踪:
Exception in thread "main" java.util.concurrent.ExecutionException: com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: connect timed out at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895) at ClientCredentialGrant.getAccessTokenByClientCredentialGrant(ClientCredentialGrant.java:78) at ClientCredentialGrant.main(ClientCredentialGrant.java:36) Caused by: com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: connect timed out at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequest(HttpHelper.java:53) at com.microsoft.aad.msal4j.AadInstanceDiscoveryProvider.executeRequest(AadInstanceDiscoveryProvider.java:218) at com.microsoft.aad.msal4j.AadInstanceDiscoveryProvider.sendInstanceDiscoveryRequest(AadInstanceDiscoveryProvider.java:172) at com.microsoft.aad.msal4j.AadInstanceDiscoveryProvider.doInstanceDiscoveryAndCache(AadInstanceDiscoveryProvider.java:271) at com.microsoft.aad.msal4j.AadInstanceDiscoveryProvider.getMetadataEntry(AadInstanceDiscoveryProvider.java:56) at com.microsoft.aad.msal4j.AuthenticationResultSupplier.getAuthorityWithPrefNetworkHost(AuthenticationResultSupplier.java:32) at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.execute(AcquireTokenByAuthorizationGrantSupplier.java:59) at com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier.acquireTokenByClientCredential(AcquireTokenByClientCredentialSupplier.java:63) at com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier.execute(AcquireTokenByClientCredentialSupplier.java:49) at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:59) at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:17) at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) Caused by: java.net.SocketTimeoutException: connect timed out at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:673) at sun.net.NetworkClient.doConnect(NetworkClient.java:175) at sun.net.www.http.HttpClient.openServer(HttpClient.java:463) at sun.net.www.http.HttpClient.openServer(HttpClient.java:558) at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264) at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:367) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191) at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1138) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1032) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338) at com.microsoft.aad.msal4j.DefaultHttpClient.readResponseFromConnection(DefaultHttpClient.java:107) at com.microsoft.aad.msal4j.DefaultHttpClient.executeHttpGet(DefaultHttpClient.java:47) at com.microsoft.aad.msal4j.DefaultHttpClient.send(DefaultHttpClient.java:35) at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequestWithRetries(HttpHelper.java:96) at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequest(HttpHelper.java:49) ... 16 more
任何帮助都将不胜感激。
我终于想通了。写下这个答案,希望能帮助到别人。com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: connect timed out
此异常是由代理问题引起的。
我的系统在代理服务器后面,所以它不能连接microsoftonline
服务器。
我有两种方法从azure AD
中获得access_token
。
第一种方法使用AZURE AD
提供的REST API
public String getAccessToken() throws UnsupportedOperationException, IOException {
ObjectMapper mapper = new ObjectMapper();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("your_proxy_address", your_proxy_port));
OkHttpClient client = new OkHttpClient.Builder().proxy(proxy).build();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(
"grant_type=client_credentials&client_id=your_client_id&scope=https://graph.microsoft.com/.default&client_secret=your_client_secret",
mediaType);
Request request = new Request.Builder()
.url("https://login.microsoftonline.com/your tenent id/oauth2/v2.0/token")
.method("POST", body).addHeader("Content-Type", "application/x-www-form-urlencoded").build();
Response response = client.newCall(request).execute();
// String token = response.body().string();
return mapper.readTree(response.body().string()).get("access_token").asText();
}
您可以使用此方法获得access_token
。另一种方法是使用MSAL4J
库。第二种方法
第一个构建客户端object
private static void BuildConfidentialClientObject() throws Exception {
Proxy proxy = AuthProvider.getInstance().getProxy();
app = ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(secret))
.proxy(proxy).authority(authority).build();
}
然后得到access_token
private static IAuthenticationResult getAccessTokenByClientCredentialGrant() throws Exception {
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters
.builder(Collections.singleton(scope)).build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
return future.join();
}
现在你可以使用这个access_token
访问graph APIs
并完成你的任务。
PS:我使用demon
方法来完成我的任务。有不同的方法来满足您的需求。
您可以在这里查看身份验证方法参考。