java - 使用 Java 连接 Azure Key Vault 时出错

标签 java azure azure-active-directory azure-keyvault azure-java-sdk

我对 Azure 相关概念不熟悉,在连接 Azure Key Vault 时遇到问题。

请找到我的代码片段如下,并让我知道为什么会出现以下异常:

Get Key started.../n SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Get Key failedjava.lang.RuntimeException: java.util.concurrent.ExecutionException: com.microsoft.aad.adal4j.AuthenticationException: {"error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: 13f8e909-89d8-472f-a1c1-9f4bcf693700\r\nCorrelation ID: bf818c41-4092-4f7d-8292-b1275a5da62f\r\nTimestamp: 2017-10-17 07:22:12Z","error":"invalid_client"} Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: com.microsoft.aad.adal4j.AuthenticationException: {"error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: 1234\r\nCorrelation ID: 123456\r\nTimestamp: 2017-10-17 07:22:12Z","error":"invalid_client"} at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:299) at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:286) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) at Program.main(Program.java:88)

相应的代码正在尝试连接 Azure Key Vault:

KeyVaultCredentials kvCred = new ClientSecretKeyVaultCredential("clientID", "client Secret");
    KeyVaultClient vc = new KeyVaultClient(kvCred);



    byte[] byteText = textToEncrypt.getBytes("UTF-16");

    /*************************************/

    // Get Key from Key Vault
    System.out.println("Get Key started.../n");

    start = System.currentTimeMillis();
    ServiceCallback<KeyBundle> serviceCallbackgetkey = new ServiceCallback<KeyBundle>(){
        @Override
        public void failure(Throwable t) {
            System.out.println("Get Key failed"+t.toString());

        }

        @Override
        public void success(KeyBundle result ) {//ServiceResponse
            System.out.println("Get Key Success");
            JsonWebKey myKey = result.key();
            keyIdentifier =  myKey.kid();
            System.out.println("Key ID:"+keyIdentifier);
            end = System.currentTimeMillis();       
            formatter = new DecimalFormat("#0.00000");
            System.out.print("Get Key Execution time is " + formatter.format((end - start) / 1000d) + " seconds\n");
            start = 0;
            end =0;
         }
    };

    ServiceCall<KeyBundle> call = vc.getKeyAsync(keyVaultURI, "MyKey1", serviceCallbackgetkey);

    System.out.println(call.get());

注意:我在 postman 中使用相同的客户端 ID 和客户端 key 来连接不同的 REST api 并且工作正常。

此外,我尝试从 here 执行以下代码。但面临同样的问题。

请帮助我确定为什么无法连接保管库。

最佳答案

我尝试重现您的问题,但失败了。

我认为您的问题可能是由于为您的应用程序授权 keyvault API 的权限造成的。

您可以引用下面对我有用的代码。

程序类别:

import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;

import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;


public class Program {

    public static void main(String[] args)
            throws InterruptedException, ExecutionException, URISyntaxException, UnsupportedEncodingException {

        KeyVaultCredentials kvCred = new ClientSecretKeyVaultCredential("APP_ID", "APP_SECRET");
        KeyVaultClient vc = new KeyVaultClient(kvCred);
        String keyIdentifier = "https://jaygong.vault.azure.net/keys/jaytest/b21bae081025418c806d73affc2937e0";
        System.out.println(vc.getKey(keyIdentifier));

    }
}

ClientSecretKeyVaultCredential 类:

import java.net.MalformedURLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;

public class ClientSecretKeyVaultCredential extends KeyVaultCredentials {
    private String applicationId;
    private String applicationSecret;

    public ClientSecretKeyVaultCredential(String applicationId, String applicationSecret) {
        this.setApplicationId(applicationId);
        this.setApplicationSecret(applicationSecret);
    }

    public String getApplicationId() {
        return applicationId;
    }

    private void setApplicationId(String applicationId) {
        this.applicationId = applicationId;
    }

    public String getApplicationSecret() {
        return applicationSecret;
    }

    private void setApplicationSecret(String applicationSecret) {
        this.applicationSecret = applicationSecret;
    }

    @Override
    public String doAuthenticate(String authorization, String resource, String scope) {
        AuthenticationResult res = null;

        try {
            res = GetAccessToken(authorization, resource, applicationId, applicationSecret);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return res.getAccessToken();
    }

    private AuthenticationResult GetAccessToken(String authorization, String resource, String clientID, String clientKey)
            throws InterruptedException, ExecutionException {
        AuthenticationContext ctx = null;
        ExecutorService service = Executors.newFixedThreadPool(1);
        try {
            ctx = new AuthenticationContext(authorization, false, service);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Future<AuthenticationResult> resp = ctx.acquireToken(resource, new ClientCredential(
                clientID, clientKey), null);
        AuthenticationResult res = resp.get();
        return res;
    }

}

结果:

enter image description here

请注意,您应该授权您的应用程序使用该 key 或 secret 。 这是 official doc 中提到的 powershell 方式.

Set-AzureRmKeyVaultAccessPolicy -VaultName 'XXXXXXX' -ServicePrincipalName XXXXX -PermissionsToKeys decrypt,sign,get,unwrapKey
<小时/>

更新答案:

我不确定您的应用程序是否有权调用 KeyVault API。您可以在门户上添加此权限。

enter image description here

希望对您有帮助。

关于java - 使用 Java 连接 Azure Key Vault 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46784774/

相关文章:

java - Powermock 或 EasyMock junits

azure - 在同一资源组中使用 ARM 模板创建两个不同的 VM

c# - 将文件上传到 Hbase HDInsight

Azure Active Directory 应用程序服务主体更新客户端 key

java - 如何在持续集成服务器中使用 FatJar(在 Eclipse 之外)?

java - 想要在值为 NULL 或 VOID 时显示错误消息(如果 EditText 为空但应用程序不断崩溃)

Javascript 客户端从 Java Web 套接字读取

asp.net - 您可以在 IIS 中运行 asp.net core 3.0 gRPC CLIENT 吗? (可能在 Azure 上?)

c# - 如何获取Azure存储帐户 key

azure - 使用 Terraform 配置 Azure AD Databricks SCIM 应用程序