Buscar este blog

martes, 27 de marzo de 2018

X509 Certificate Mock Servlet Filter

This is a way low-technolgy-solution to simulate, in web application, an SSL mutual authentication.  The obvious solution would be to configure Apache httpd as front-end, and let it to ask for the user certificate, but I had some problems with an android web browser...
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