web-dev-qa-db-fra.com

Spring REST Authentification du certificat de service

J'ai écrit le contrôleur Spring. Cette demande reçoit des clients. C'est juste REST style.

C'est très bien. Mais j'ai besoin d'une authentification par certificat. Seuls les clients doivent avoir accès au service de repos (contrôleur à ressort), qui dispose de certificats client avec clé (en d'autres termes, le client doit avoir un magasin de clés avec clé).

Comment puis-je configurer cette sécurité au printemps? Pourriez-vous me donner un exemple ou un lien où cela est écrit?

Merci

14
grep

Ce que vous recherchez s'appelle Authentification mutuelle .

Il est de la responsabilité des serveurs de faire/demander au client d'envoyer son certificat. Chaque serveur fait cela différemment et vous devrez chercher comment configurer votre serveur particulier.

Pour Spring Security, je recommanderais d'examiner authentification X.509 . Ce type d'authentification est assez facile à utiliser et à étendre au besoin.

[~ # ~] modifier [~ # ~]

Donc, voici quelques références qui montrent des exemples de ce que vous demandez:

http://whiteycode.blogspot.com/2012/04/part-3-x509-authentication-with-spring.html

Avertissement PDF

http://www.promixis.com/pdfs/SpringSecurityAndX509ClientCertificates.pdf

Le fichier pdf ci-dessus n'est plus accessible ...

Cet exemple est très utile pour expliquer comment configurer vos certificats et créer votre propre autorité de certification (autorité de certification) personnelle. Attention, la façon dont ils montrent la création du certificat client n'est qu'un moyen, pas le moyen. Votre client (navigateur Web IE ou Java client httpclient) doit déterminer la manière de créer votre certificat client. Java aime utiliser son Java keystore bien sûr et les navigateurs ont tendance à aimer le style p12 des certificats.

Dernier conseil/avertissement ... Je ne connais pas votre niveau de connaissance avec les certificats, mais ... L'authentification mutuelle consiste à savoir qui fait confiance à qui. C'est la responsabilité de severs de dire, j'ai besoin que vous vous authentifiiez avec un certificat et voici une liste de fournisseurs de certificats en qui j'ai confiance. Il incombe ensuite aux clients de répondre avec un certificat signé par l'un de ces fournisseurs de certificats de confiance du serveur. C'est la responsabilité des applications de dire ensuite: ai-je confiance en cette personne en fonction de son nom à l'intérieur du certificat? Si et quand les choses commencent à mal tourner, pensez à qui fait confiance ou non à qui.

Un excellent outil utilise -Djavax.net.debug = ssl sur votre application. Il montrera l'ensemble de la poignée de main SSL et ce qui est demandé et quelles sont les réponses spécifiques. Cette option est un peu prolixe, mais c'est bien d'avoir en cas de besoin.

MODIFIER X 2

Voici comment activer l'authentification mutuelle sur Tomcat 7.

Dans votre fichier de configuration server.xml, vous devriez voir près de ce qui suit pour un connecteur SSL:

<Connector port="8443" protocol="org.Apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="want" sslProtocol="TLS"
           keystoreFile="C:\Java\Certs\localhost.jks"
           keystorePass="changeit"
           URIEncoding="UTF-8" />

La valeur importante à noter est la valeur clientAuth.

Définir clientAuth sur "want" indique au client d'envoyer un certificat SSL client signé à partir d'une liste de certificats que le serveur approuve si vous en avez un. Sinon, allez-y et faites votre demande normalement.

Définir clientAuth sur "true" indique au client qu'il DOIT envoyer un certificat SSL client signé à partir d'une liste de certificats que le serveur approuve. Si vous n'avez pas de certificat signé par une liste de certificats que le serveur approuve, le client N'EST PAS autorisé à faire la demande.

La liste des certificats auxquels le serveur fait confiance provient soit de la valeur par défaut Java truststore, soit peut être définie à l'aide du -Djavax.net.ssl.trustStore="C:\Java\Certs\jssecacerts1" VM.

Généralement, lorsque vous avez un certificat CA spécifique auquel vous faites confiance et qui n'est pas dans le magasin de confiance par défaut Java, le magasin de confiance par défaut est copié, le nouveau certificat de l'autorité de certification est importé dans le magasin de confiance copié puis utilisé avec ci-dessus VM.

[~ # ~] avertissement [~ # ~]

Il est super important de NE PAS modifier le magasin de confiance par défaut Java en place. Si vous le faites, toutes les applications Java par défaut sur cette machine utiliseront la nouvelle mise à jour). Ce n'est pas toujours ce que les gens veulent et ce qui peut entraîner des risques pour la sécurité.

20
hooknc

J'ai créé un exemple de projet 100% compréhensible avec tout nécessaire pour configurer une application Spring Boot avec un point de terminaison REST qui est sécurisé par un certificat client - et un Testcase avec le RestTemplate configuré pour utiliser le certificat client pour communiquer avec le serveur sécurisé: https://github.com/jonashackt/spring-boot-rest-clientcertificate

Il contient également toutes les étapes nécessaires pour générer le .key, .crt et .jks des dossiers. Ajustez simplement les étapes en conséquence, si vous ne souhaitez pas utiliser un certificat auto-signé.

Le RestTemplate est configuré comme ceci:

package de.jonashackt.restexamples;

import org.Apache.http.client.HttpClient;
import org.Apache.http.impl.client.HttpClients;
import org.Apache.http.ssl.SSLContextBuilder;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;

@Configuration
public class RestClientCertTestConfiguration {

    private String allPassword = "allpassword";

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {

        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(ResourceUtils.getFile("classpath:keystore.jks"), allPassword.toCharArray(), allPassword.toCharArray())
                .loadTrustMaterial(ResourceUtils.getFile("classpath:truststore.jks"), allPassword.toCharArray())
                .build();

        HttpClient client = HttpClients.custom()
                .setSSLContext(sslContext)
                .build();

        return builder
                .requestFactory(new HttpComponentsClientHttpRequestFactory(client))
                .build();
    }
}

Ensuite, vous pouvez l'utiliser comme vous en avez l'habitude avec le @Autowired annotation dans votre Test.class.

4
jonashackt