1

現在、Springブートアプリケーションで相互認証を実装しており、Azureにそれを展開する必要があります。 Azureのロードバランサは、リクエストヘッダフィールド "X-ARR-ClientCert"内のクライアント証明書(Base64エンコード)をリダイレクトし、Springはそこでそれを見つけることができません。 https://docs.microsoft.com/en-gb/azure/app-service-web/app-service-web-configure-tls-mutual-authAzureのSpringブート - リクエストヘッダのクライアント証明書

IはOncePerRequestFilterのヘッダから証明書を抽出し、このような要求に設定しようとした: =>認証は、Microsoftのドキュメントは、.NETアプリケーションでこれを処理する方法を示し

失敗

public class AzureCertificateFilter extends OncePerRequestFilter { 
    private static final Logger LOG = LoggerFactory.getLogger(AzureCertifacteFilter.class); 
    private static final String AZURE_CLIENT_CERTIFICATE_HEADER = "X-ARR-ClientCert"; 
    private static final String JAVAX_SERVLET_REQUEST_X509_CERTIFICATE = "javax.servlet.request.X509Certificate"; 
    private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----\n"; 
    private static final String END_CERT = "\n-----END CERTIFICATE-----"; 

    @Override 
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { 
     X509Certificate x509Certificate = extractClientCertificate(httpServletRequest); 

     // azure redirects the certificate in a header field 
     if (x509Certificate == null && StringUtils.isNotBlank(httpServletRequest.getHeader(AZURE_CLIENT_CERTIFICATE_HEADER))) { 
      String x509CertHeader = BEGIN_CERT + httpServletRequest.getHeader(AZURE_CLIENT_CERTIFICATE_HEADER) + END_CERT; 

      try (ByteArrayInputStream certificateStream = new ByteArrayInputStream(x509CertHeader.getBytes())) { 
       X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certificateStream); 
       httpServletRequest.setAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE, certificate); 
      } catch (CertificateException e) { 
       LOG.error("X.509 certificate could not be created out of the header field {}. Exception: {}", AZURE_CLIENT_CERTIFICATE_HEADER, e.getMessage()); 
      } 
     } 

     filterChain.doFilter(httpServletRequest, httpServletResponse); 
    } 

    private X509Certificate extractClientCertificate(HttpServletRequest request) { 
     X509Certificate[] certs = (X509Certificate[]) request.getAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE); 

     if (certs != null && certs.length > 0) { 
      LOG.debug("X.509 client authentication certificate:" + certs[0]); 
      return certs[0]; 
     } 

     LOG.debug("No client certificate found in request."); 
     return null; 
    } 
} 

しかし、これは後に、次の例外を除いて春フィルタチェーンの失敗:

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

設定は次のようになります。

@Override 
public void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests() 
     .antMatchers("**/docs/restapi/**").permitAll() 
     .anyRequest().authenticated() 
     .and() 
     .httpBasic() 
     .disable() 
     .addFilterBefore(new AzureCertificateFilter(), X509AuthenticationFilter.class) 
     .x509() 
     .subjectPrincipalRegex("CN=(.*?)(?:,|$)") 
     .userDetailsService(userDetailsService()); 
} 

答えて

0

私はもっと慎重に例外を読んでいる必要があります。

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

を私はこのような証明書の配列を設定する必要がありました:

httpServletRequest.setAttribute(JAVAX_SERVLET_REQUEST_X509_CERTIFICATE, new X509Certificate[]{x509Certificate}); 
関連する問題