Saltar al contenido

¿Cómo ignorar los errores de confianza del certificado SSL en Feign?

Solución:

Descargo de responsabilidad

En realidad, no debería hacer esto por varias muy buenas razones. La forma más fácil de solucionar los problemas de SSL es seguir las mejores prácticas de SSL y utilizar certificados válidos. Hay excelentes proyectos en línea como https://letsencrypt.org/ que incluso le permitirán obtener una gran seguridad de forma gratuita si el host es de acceso público (si tiene un nombre de host real que se pueda verificar).

ÚSELO BAJO SU PROPIO RIESGO. ASEGÚRESE DE COMPRENDER QUE ESTÁ VIOLANDO MUCHAS MEJORES PRÁCTICAS Y UTILICE ESTO SOLO SI ENTIENDE ESO.

Si causa algún tipo de problema importante con este código de ejemplo, usted es responsable.

Charla honesta

Tuve el mismo problema al tratar con servicios internos (no accesibles públicamente) a los que quería llamar desde una aplicación de arranque de primavera y lo resolví usando el siguiente código.

Breve descripción

Mucha gente le dirá que puede aceptar todos los certificados, codificar su certificado particular en él o algo más. De hecho, puede permitir solo ciertos hosts confiables a través de la ruta de código, que es lo que estoy intentando aquí para una capa adicional de seguridad.

En este código de ejemplo, puede pasar varios hosts a las clases y debería permitir que las solicitudes solo a esos hosts se emitan con certificados no válidos, y todo lo demás pasará por la cadena de mando normal.

Este no es realmente un código de grado de producción, pero es de esperar que pueda aprovecharlo.

Basta de conferencias, lo que sigue puede que te interese más.

El código

Esto se usa para Java 8 y spring-boot.

Configuración

@Configuration
    public class FeignClientConfiguration {

    @Bean
    public Client client() throws NoSuchAlgorithmException, 
        KeyManagementException {

        return new Client.Default(
            new NaiveSSLSocketFactory("your.host.here"),
            new NaiveHostnameVerifier("your.host.here"));
    }
}

NaiveHostnameVerifier

public class NaiveHostnameVerifier implements HostnameVerifier {
    private final Set<String> naivelyTrustedHostnames;

    private final HostnameVerifier hostnameVerifier =
        HttpsURLConnection.getDefaultHostnameVerifier();

    public NaiveHostnameVerifier(String ... naivelyTrustedHostnames) {
        this.naivelyTrustedHostnames =
                Collections.unmodifiableSet(
                    new HashSet<>(Arrays.asList(naivelyTrustedHostnames)));
    }

    @Override
    public boolean verify(String hostname, SSLSession session) {
        return naivelyTrustedHostnames.contains(hostname) ||
                hostnameVerifier.verify(hostname, session);
    }
}

NaiveSSLSocketFactory

public class NaiveSSLSocketFactory extends SSLSocketFactory {
    private final SSLSocketFactory sslSocketFactory = 
                    (SSLSocketFactory) SSLSocketFactory.getDefault();

    private final SSLContext alwaysAllowSslContext;
    private final Set<String> naivelyTrustedHostnames;

    public NaiveSSLSocketFactory(String ... naivelyTrustedHostnames) 
        throws NoSuchAlgorithmException, KeyManagementException {

        this.naivelyTrustedHostnames = 
                Collections.unmodifiableSet(
                    new HashSet<>(Arrays.asList(naivelyTrustedHostnames)));

        alwaysAllowSslContext = SSLContext.getInstance("TLS");
        TrustManager tm = new X509TrustManager() {

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) 
                throws CertificateException {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                    return null;
            }
        };

        alwaysAllowSslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return sslSocketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return sslSocketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return (naivelyTrustedHostnames.contains(host)) 
            ? alwaysAllowSslContext.getSocketFactory().createSocket(socket, host, port, autoClose) 
            : sslSocketFactory.createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return (naivelyTrustedHostnames.contains(host)) 
            ? alwaysAllowSslContext.getSocketFactory().createSocket(host, port) 
            : sslSocketFactory.createSocket(host, port);
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException, UnknownHostException {
        return (naivelyTrustedHostnames.contains(host)) 
            ? alwaysAllowSslContext.getSocketFactory().createSocket(host, port, localAddress, localPort) 
            : sslSocketFactory.createSocket(host, port, localAddress, localPort);
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return (naivelyTrustedHostnames.contains(host.getHostName())) 
            ? alwaysAllowSslContext.getSocketFactory().createSocket(host, port) 
            : sslSocketFactory.createSocket(host, port);
    }

    @Override
    public Socket createSocket(InetAddress host, int port, InetAddress localHost, int localPort) throws IOException {
        return (naivelyTrustedHostnames.contains(host.getHostName())) 
            ? alwaysAllowSslContext.getSocketFactory().createSocket(host, port, localHost, localPort) 
            : sslSocketFactory.createSocket(host, port, localHost, localPort);
    }
}

Referencias

Tomé prestado mucho de esta respuesta:

Confiar en todos los certificados usando HttpClient sobre HTTPS

Cuando usas Spring Cloud Netflix> = 1.4.4. también puede hacer lo siguiente:

Agregar okhttp dependencia de maven del cliente:

    <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-okhttp</artifactId>
    </dependency>

Y agregue las siguientes propiedades:

feign.httpclient.disableSslValidation=true
feign.httpclient.enabled=false
feign.okhttp.enabled=true

Referencia: https://github.com/spring-cloud/spring-cloud-netflix/issues/2729

feign.httpclient.disableSslValidation = true no me funcionó.

Se trabaja Crear bean de cliente en Configuración mediante el siguiente código:

import feign.Client;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.ssl.SSLContexts;
import org.springframework.context.annotation.Bean;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

public class ClientConfiguration {

    @Bean
    public Client feignClient() {
        return new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
    }

    private SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
            return sslContext.getSocketFactory();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

}

pom.xml podría necesitar agregar dependencias:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.8</version>
    </dependency>
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *