spring Azure中的Sping Boot -请求标头中的客户端证书

kmbjn2e3  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(179)

我们目前在Sping Boot 应用程序中实现了相互身份验证,需要在Azure中部署它。Azure的负载平衡器在请求头字段“X-ARR-ClientCert”中重定向客户端证书(Base64编码),Spring无法在那里找到它。=>身份验证失败
Microsoft文档展示了如何在.NET应用程序中处理此问题:https://learn.microsoft.com/en-gb/azure/app-service-web/app-service-web-configure-tls-mutual-auth
我试着从OncePerRequestFilter的头中提取证书,并将其设置为请求如下:

  1. public class AzureCertificateFilter extends OncePerRequestFilter {
  2. private static final Logger LOG = LoggerFactory.getLogger(AzureCertifacteFilter.class);
  3. private static final String AZURE_CLIENT_CERTIFICATE_HEADER = "X-ARR-ClientCert";
  4. private static final String JAVAX_SERVLET_REQUEST_X509_CERTIFICATE = "javax.servlet.request.X509Certificate";
  5. private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----\n";
  6. private static final String END_CERT = "\n-----END CERTIFICATE-----";
  7. @Override
  8. protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
  9. X509Certificate x509Certificate = extractClientCertificate(httpServletRequest);
  10. // azure redirects the certificate in a header field
  11. if (x509Certificate == null && StringUtils.isNotBlank(httpServletRequest.getHeader(AZURE_CLIENT_CERTIFICATE_HEADER))) {
  12. String x509CertHeader = BEGIN_CERT + httpServletRequest.getHeader(AZURE_CLIENT_CERTIFICATE_HEADER) + END_CERT;
  13. try (ByteArrayInputStream certificateStream = new ByteArrayInputStream(x509CertHeader.getBytes())) {
  14. X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certificateStream);
  15. httpServletRequest.setAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE, certificate);
  16. } catch (CertificateException e) {
  17. LOG.error("X.509 certificate could not be created out of the header field {}. Exception: {}", AZURE_CLIENT_CERTIFICATE_HEADER, e.getMessage());
  18. }
  19. }
  20. filterChain.doFilter(httpServletRequest, httpServletResponse);
  21. }
  22. private X509Certificate extractClientCertificate(HttpServletRequest request) {
  23. X509Certificate[] certs = (X509Certificate[]) request.getAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE);
  24. if (certs != null && certs.length > 0) {
  25. LOG.debug("X.509 client authentication certificate:" + certs[0]);
  26. return certs[0];
  27. }
  28. LOG.debug("No client certificate found in request.");
  29. return null;
  30. }
  31. }

字符串
但这在Spring filter链中会失败,但有以下例外:

  1. sun.security.x509.X509CertImpl cannot be cast to [Ljava.security.cert.X509Certificate; /oaa/v1/spaces


配置如下所示:

  1. @Override
  2. public void configure(HttpSecurity http) throws Exception {
  3. http.authorizeRequests()
  4. .antMatchers("**/docs/restapi/**").permitAll()
  5. .anyRequest().authenticated()
  6. .and()
  7. .httpBasic()
  8. .disable()
  9. .addFilterBefore(new AzureCertificateFilter(), X509AuthenticationFilter.class)
  10. .x509()
  11. .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
  12. .userDetailsService(userDetailsService());
  13. }

bqjvbblv

bqjvbblv1#

我应该更仔细地阅读例外:

  1. sun.security.x509.X509CertImpl cannot be cast to [Ljava.security.cert.X509Certificate; /oaa/v1/spaces

字符串
我必须设置一个像这样的证书数组:

  1. httpServletRequest.setAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE, new X509Certificate[]{x509Certificate});

相关问题