So, instead configure Apache with a "SSLVerifyClient require" this is my ashamed solution: to configure a servlet filter (at first position in the chain) and, if there is no certificate in the request, just put one and go on.
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class X509CertificateFilter implements Filter {
    private static final Logger LOGGER = LoggerFactory.getLogger(X509CertificateFilter.class);
    
    private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\r\n" + 
            "MIIIdDCCB1ygAwIBAgIQIDbcJ3psq8FXD6IQBZA15DANBgkqhkiG9w0BAQsFADBN\r\n" +             
            "(...)\r\n" + 
            "740qIwTZlA4=\r\n" + 
            "-----END CERTIFICATE-----";
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {                
    }
    @Override
    public void destroy() {        
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (request.getAttribute("javax.servlet.request.X509Certificate") == null) {
            request.setAttribute("javax.servlet.request.X509Certificate", buildCertificates());
        }
        
        chain.doFilter(request, response);    
    }
    private static X509Certificate[] buildCertificates() {
        try {        
            final InputStream is = new ByteArrayInputStream(CERTIFICATE.getBytes());                    
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
            return new X509Certificate[] {cert};
        }
        catch(Exception e) {
            LOGGER.error("Error injecting certificate", e);
            return null;
        }
    }    
}
You can also configure multiple certificates, for example in a map, and use a request parameter to pick one...
No hay comentarios:
Publicar un comentario