java - 如何访问 Spring 托管类中的 keyvault 属性?
问题描述
我正在使用 azure keyvault 来存储应用程序机密。我想在 spring 托管组件类中使用它们。什么时候,我试图访问它。它抛出空指针异常。有人可以建议在 Spring Boot 中访问属性的理想方法是什么。
@Slf4j
@Component
public class AuthConfiguration extends HandlerInterceptorAdapter {
private static final String CORRELATION_ID_LOG_VAR_NAME = "correlationId";
private static final String CORRELATION_ID_HEADER_NAME = "Correlation-Id";
@Autowired
KeyVaultProperties keyVaultProperties;
@Value("${private-key-alias-name}")
private String KeyAliasName;
@Value("${auth-cert-password}")
private String AuthCertPassword;
@PostConstruct
public void setup(){
ClassLoader classLoader = AuthConfiguration.class.getClassLoader();
File file = new File(
Objects.requireNonNull(
classLoader.getResource(AppConstants.JKS_FILE_NAME))
.getFile());
KeyStore keystore = null;
try {
InputStream is = new FileInputStream(file);
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, AuthCertPassword.toCharArray());
key = (PrivateKey)keystore.getKey(KeyAliasName, AuthCertPassword.toCharArray());
} catch (UnrecoverableKeyException | KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) {
e.printStackTrace();
}
}
@Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler)
throws Exception {
final Boolean isValidToken;
final String correlationId = getCorrelationIdFromHeader(request);
isValidToken = validateAuthTokenFromRequestHeader(request);
log.info("correlationId:{}",correlationId);
MDC.put(CORRELATION_ID_LOG_VAR_NAME, correlationId);
log.info("Token is Valid:{}",isValidToken);
if(!isValidToken)
throw new AuthenticationException("Invalid Authentication");
return isValidToken;
}
@Override
public void afterCompletion(final HttpServletRequest request, final HttpServletResponse response,
final Object handler, final Exception ex) throws Exception {
MDC.remove(CORRELATION_ID_LOG_VAR_NAME);
}
private String getCorrelationIdFromHeader(final HttpServletRequest request) {
String correlationId = request.getHeader(CORRELATION_ID_HEADER_NAME);
if (correlationId == null) {
correlationId = generateUniqueCorrelationId();
}
return correlationId;
}
private Boolean byPassToken(final HttpServletRequest request){
String byPassToken = request.getHeader(BY_PASS_TOKEN);
return (byPassToken != null) && byPassToken.equals("true");
}
private String generateUniqueCorrelationId() {
return UUID.randomUUID().toString();
}
private Boolean validateAuthTokenFromRequestHeader(final HttpServletRequest request)
throws ParseException, ValidationException{
String authToken = request.getHeader(AUTH_TOKEN_HEADER_NAME);
if(authToken == null){
log.info("Token is Empty for this request, correlation Id: {}",request.getHeader(CORRELATION_ID_HEADER_NAME));
throw new ValidationException(Error.MISSING_AUTH_TOKEN.getCode(),Error.MISSING_AUTH_TOKEN.getErrorMsg());
}
JWTClaimsSet claimsSet = decryption(authToken);
return
isValidIssuer(claimsSet);
}
private JWTClaimsSet decryption(String encryptedJWTString)
throws ParseException, AuthenticationException {
EncryptedJWT jwt = null;
try{
jwt = EncryptedJWT.parse(encryptedJWTString);
RSADecrypter decrypter = new RSADecrypter(key);
jwt.decrypt(decrypter);
}catch (ParseException exception){
throw new AuthenticationException(Error.MISSING_AUTH_TOKEN.getErrorMsg());
}catch (Exception e){
e.printStackTrace();
}
return jwt.getJWTClaimsSet();
}
// Check if token issuer is valid
private Boolean isValidIssuer(JWTClaimsSet jwtClaimsSet){
log.info("Issuer is Valid:{}",jwtClaimsSet.getIssuer().equals(keyVaultProperties.getAuthIssuer()));
return jwtClaimsSet.getIssuer().equals(issuer);
}
}
@Data
public class KeyVaultProperties {
@Value("${auth-by-pass-token}")
private String AuthByPassToken;
@Value("${auth-clients}")
private String authClients;
@Value("${auth-cert-password}")
private String AuthCertPassword;
@Value("${auth-issuer}")
private String AuthIssuer;
}
我在log.info("Issuer is Valid:{}",jwtClaimsSet.getIssuer().equals(keyVaultProperties.getAuthIssuer()));
. 有人可以帮我吗,我可以在postconstruct
方法设置中访问相同的属性
解决方案
我认为获取密钥库机密的最简单方法是使用托管标识,当然它为 java 提供了解决方案,这里是关于 java 的azure idenetity 客户端库的描述。我已经测试了从客户端凭据流生成的凭据之一。这里还有一些其他选项,您可以选择使用其他选项。请注意,您需要在 azure key vault 中为目标 azure-ad-app 或其他一些服务原则授予访问策略。
public static void main(String args[]) {
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId("azure ad application client id")
.clientSecret("client secret")
.tenantId("xxx.onmicrosoft.com")
.build();
// Azure SDK client builders accept the credential as a parameter
SecretClient client = new SecretClientBuilder()
.vaultUrl("https://{YOUR_VAULT_NAME}.vault.azure.net")
.credential(clientSecretCredential)
.buildClient();
String a = client.getSecret("cosmosdbScanWithwrongkey").getValue();
System.out.print(a);
}
推荐阅读
- php - $oQueryBuilder->getQuery()->getResult() 的问题
- python - Python脚本关闭时结束执行子进程
- c++ - 复数相除 - 条件
- android - 我可以在 android studio 的片段上使用 Firebase 吗?
- sorting - 获得shell排序通过次数的公式是什么?
- unity3d - Unity 在鼠标点处实例化对象得到错误的坐标
- c# - 在不知道结构的情况下使用 Newtonsoft.Json 解析 JSON
- nuxt.js - 在 Nuxt w/ Express 中如何在保存服务器时防止重新编译
- swift - 将访问从 tableViewController 传递到另一个视图控制器
- reactjs - 反应路由器同时显示多个组件