java - 从 azure keyvault azure Java servlet 获取机密
问题描述
我正在尝试从 azure keyvault 中获取秘密。当我独立于 main 方法运行类时,它返回秘密,但是当我在代码行 future.get() 的 servlet 应用程序中集成相同的代码时;在这里它得到块它不会像死锁一样继续等待它一直等待并且有时会得到 java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List 和 com.microsoft .azure.keyvault.models.KeyVaultErrorException:状态码 401,{"error":{"code":"Unauthorized","message":"AKV10001:无法解析 JWT 令牌:预期 3 个紧凑型 JSON 元素,找到 1 个。" }} 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 。请帮助我。
public class KeyVaultTest {
private static AuthenticationResult getAccessToken(String authorization, String resource) throws InterruptedException, ExecutionException, MalformedURLException {
String clientId = "XXX"; // Client ID
String clientSecret = "XXX"; //Client Secret
AuthenticationResult result = null;
//Starts a service to fetch access token.
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
AuthenticationContext context = new AuthenticationContext(authorization, false, service);
Future<AuthenticationResult> future = null;
//Acquires token based on client ID and client secret.
if (clientSecret != null && clientSecret != null) {
ClientCredential credentials = new ClientCredential(clientId, clientSecret);
future = context.acquireToken(resource, credentials, null);
}
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new RuntimeException("Authentication results were null.");
}
return result;
}
public static void main(String[] args) {
String vaultBase = "https://myapp-keyvault.vault.azure.net/";
KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultCredentials(){
@Override
public String doAuthenticate(String authorization, String resource, String scope) {
String token = null;
try {
AuthenticationResult authResult = getAccessToken(authorization, resource);
token = authResult.getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(token);
return token;
}
});
SecretBundle secretBundle = keyVaultClient.getSecret(vaultBase, "abc");
System.out.println(secretBundle.value());
}
解决方案
如果您想在您的 servlet 应用程序中访问 Azure 密钥保管库,请参考以下步骤
- 配置 Azure 密钥保管库
#create service pricipal
az ad sp create-for-rbac -n "MyApp" --password "hVFkk965BuUv" --skip-assignment --sdk-auth
#set access policy
az keyvault set-policy -n <your-unique-keyvault-name> --spn <clientId-of-your-service-principal> --secret-permissions list get set delete purge
应用
一个。SDK
<dependency> <groupId>com.microsoft.azure</groupId> <artifactId>adal4j</artifactId> <version>1.6.5</version> </dependency> <dependency> <groupId>com.microsoft.azure</groupId> <artifactId>azure-keyvault</artifactId> <version>1.2.4</version> </dependency>
湾。小服务程序类
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public HelloServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String appId="42e0d080-b1f3-40cf-8db6-c4c522d988c4";
String appSecret="Gbx2eK64iqq_g_3NCA.ClJDfQpIjoae:";
KeyVaultClient keyVaultClient = new KeyVaultClient(new AzureKeyVaultCredential(appId,appSecret));
String vaultBaseUrl="https://testsql08.vault.azure.net/";
String secretName="sql";
SecretBundle secret =keyVaultClient.getSecret(vaultBaseUrl, secretName);
System.out.println(secret.value());
PrintWriter writer = response.getWriter();
writer.println("<h1>Hello " + secret.value() + "</h1>");
writer.close();
}
}
class AzureKeyVaultCredential extends KeyVaultCredentials {
private String appId;
private String appSecret;
public AzureKeyVaultCredential(String appId, String appSecret) {
this.appId = appId;
this.appSecret = appSecret;
}
@Override
public String doAuthenticate(String authorization, String resource, String scope) {
AuthenticationContext context = null;
AuthenticationResult result = null;
String token = "";
try {
context = new AuthenticationContext(authorization, false, Executors.newSingleThreadExecutor());
ClientCredential credential = new ClientCredential(this.appId, this.appSecret);
Future<AuthenticationResult> future = context.acquireToken(resource, credential, null);
result = future.get(3, TimeUnit.MINUTES);
token = result.getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
}
推荐阅读
- ios - Parsing CloudKit Error (CKError)
- angularjs - 使用带有ng-repeat的自定义排序时Angularjs无限摘要错误
- sql - 特定 ID 中的 SQL 帮助
- javascript - 单击网页中的多个按钮会中止已经长时间运行的 ajax 调用吗?
- django - Django 2 - 添加用户错误 - 具有此名称的组已存在
- python - python函数在调用范围内修改变量
- ios - 如何在 swift 中将 ISO 4217 代码转换为货币代码
- python - 将列表和图像作为 keras 模型的输入
- python - Pyodbc 连接给出奇怪的错误
- android - 文档引用在集合引用上必须有偶数段错误