X.509-Authentifizierung in Spring Security

X.509 Authentication in Spring Security

1. Überblick

In diesem Artikel konzentrieren wir uns auf die Hauptanwendungsfälle fürX.509 certificate authentication -verifying the identity of a communication peer, wenn das ProtokollHTTPS (HTTP over SSL) verwendet wird.

Einfach ausgedrückt: Während eine sichere Verbindung hergestellt wird, überprüft der Client den Server anhand seines Zertifikats (ausgestellt von einer vertrauenswürdigen Zertifizierungsstelle).

Darüber hinaus könnenX.509 inSpring Security während der Verbindung über den Server zuverify the identity of a client verwendet werden. Dies wird als“mutual authentication, “bezeichnet und wir werden uns auch hier ansehen, wie das gemacht wird.

Schließlich werden wirwhen it makes sense to use this kind of authentication ansprechen.

Um die Serverüberprüfung zu demonstrieren, erstellen wir eine einfache Webanwendung und installieren eine benutzerdefinierte Zertifizierungsstelle in einem Browser.

Fürmutual authentication erstellen wir ein Client-Zertifikat und ändern unseren Server so, dass nur verifizierte Clients zugelassen werden.

2. Keystores

Optional Requirement: Um kryptografisch starke Schlüssel zusammen mit Verschlüsselungs- und Entschlüsselungsfunktionen zu verwenden, müssen Sie die‘Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files' in IhrenJVM. installieren

Diese können beispielsweise vonOracle heruntergeladen werden (befolgen Sie die im Download enthaltenen Installationsanweisungen). Einige Linux-Distributionen bieten über ihre Paketmanager auch ein installierbares Paket an.

UmX.509 authentication in einer Spring-Anwendung zu implementieren, verwenden wirfirst create a keystore in the Java Key-Store (JKS) format.

Diesekeystore müssencontain a valid certificate of authority or a chain of certificate authorities und ein eigenes Zertifikat für unseren Server sein. Letzteres muss von einem der enthaltenenauthorities signiert und nach denhostname benannt sein, auf denen der Server ausgeführt wird. Wir werden hier die AnwendungJavakeytoolverwenden.

To simplify Der Prozess zum Erstellen vonkeys undcertificates unter Verwendung vonkeytool, dem Codeon Github, liefert einen kommentiertenMakefile für GNUmake , enthält alle Schritte, die zum Ausfüllen dieses Abschnitts erforderlich sind. Sie können es auch einfach über einige Umgebungsvariablen anpassen.

Tip: Alsall-in-one step können Siemake ohne Argumente ausführen. Dadurch werden einkeystore, eintruststore und zwei Zertifikate für den Import in Ihren Browser erstellt (eines fürlocalhost und eines für einen Benutzer namens“cid”).

Zum Erstellen eines neuenkeystore mit einer Zertifizierungsstelle können wirmake wie folgt ausführen:

$> make create-keystore PASSWORD=changeit

Jetzt fügen wir diesem erstelltenkeystore ein Zertifikat für unseren Entwicklungshost hinzu und signieren es mit unseremcertificate authority:

$> make add-host HOSTNAME=localhost

Umclient authentication zuzulassen, benötigen wir auchkeystore namens“truststore”. Diesetruststore müssen gültige Zertifikate unserercertificate authority und aller zulässigen Clients enthalten. Hinweise zur Verwendung vonkeytool finden Sie in denMakefile in den folgenden Abschnitten:

$> make create-truststore PASSWORD=changeit
$> make add-client CLIENTNAME=cid

3. Beispielanwendung

Unser SSL-gesichertes Serverprojekt besteht aus einer mit Anmerkungen versehenen Anwendungsklasse von@SpringBootApplication(eine Art@Configuration), einer Konfigurationsdatei vonapplication.propertiesund einem sehr einfachen Front-End im MVC-Stil.

Die Anwendung muss lediglich eineHTML-Seite mit einer“Hello {User}!”-Seite anzeigen. Auf diese Weise können wir das Serverzertifikat in einem Browser überprüfen, um sicherzustellen, dass die Verbindung überprüft und gesichert wurde.

Zuerst erstellen wir ein neuesMaven-Projekt mit dreiSpring Boot Starter-Bundles:


    org.springframework.boot
    spring-boot-starter-security
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-web
    1.4.0.RELEASE


    org.springframework.boot
    spring-boot-starter-thymeleaf
    1.4.0.RELEASE

For reference: finden Sie die Bündel aufMaven Central (security,web,thymeleaf).

Im nächsten Schritt erstellen wir die Hauptanwendungsklasse und den User-Controller:

@SpringBootApplication
public class X509AuthenticationServer {
    public static void main(String[] args) {
        SpringApplication.run(X509AuthenticationServer.class, args);
    }
}

@Controller
public class UserController {
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {

        UserDetails currentUser
          = (UserDetails) ((Authentication) principal).getPrincipal();
        model.addAttribute("username", currentUser.getUsername());
        return "user";
    }
}

Jetzt teilen wir der Anwendung mit, wo sie unserekeystorefinden kann und wie darauf zugegriffen werden kann. Wir setzenSSL auf einen "aktivierten" Status und ändern den Standard-Listening-Port aufindicate a secured connection.

Zusätzlich konfigurieren wir einigeuser-details für den Zugriff auf unseren Server überBasic Authentication:

server.ssl.key-store=../keystore/keystore.jks
server.ssl.key-store-password=${PASSWORD}
server.ssl.key-alias=localhost
server.ssl.key-password=${PASSWORD}
server.ssl.enabled=true
server.port=8443
security.user.name=Admin
security.user.password=admin

Dies ist die HTML-Vorlage, die sich im Ordnerresources/templatesbefindet:




    X.509 Authentication Demo


    

Hello !

Bevor wir diesen Abschnitt beenden und uns die Site ansehen, müssen wir unsere generierte Zertifizierungsstelle noch alstrusted certificate in einem Browser unserer Wahl installieren.

Eine beispielhafte Installation unserercertificate authority fürMozilla Firefox würde wie folgt aussehen:

  1. Geben Sieabout:preferences in die Adressleiste ein

  2. Öffnen SieAdvanced → Certificates → View Certificates → Authorities

  3. Klicken Sie aufImport

  4. Suchen Sie den Ordnerexample tutorials und seinen Unterordnerspring-security-x509/keystore

  5. Wählen Sie die Dateica.crt aus und klicken Sie aufOK

  6. Wählen Sie „Trust this CA to identify websites” und klicken Sie aufOK

Note: Wenn Sie unserecertificate authority nicht zur Liste dertrusted authorities hinzufügen möchten, haben Sie später die Möglichkeit,exception zu erstellen und die Website hart zu zeigen. auch wenn es als unsicher bezeichnet wird. In der Adressleiste wird jedoch ein gelbes Ausrufezeichen angezeigt, das auf die unsichere Verbindung hinweist.

Anschließend navigieren wir zum Modul spring-security-x509-basic-auth und führen Folgendes aus:

mvn spring-boot:run

Schließlich drücken wirhttps://localhost:8443/user, geben unsere Benutzeranmeldeinformationen ausapplication.properties ein und sollten eine“Hello Admin!”-Nachricht sehen. Jetzt können wir den Verbindungsstatus überprüfen, indem wir auf das grüne Schlosssymbol in der Adressleiste klicken. Es sollte sich um eine gesicherte Verbindung handeln.

image

 

4. Gegenseitige Authentifizierung

In diesem Abschnitt verwenden wirSpring Security, um Benutzern Zugriff auf unsere Demo-Website zu gewähren. Das Verfahren macht ein Anmeldeformular überflüssig.

Bevor wir unseren Server jedoch weiter modifizieren, werden wir kurz diskutieren, wann es sinnvoll ist, diese Art der Authentifizierung bereitzustellen.

Vorteile:

  • Der private Schlüssel vonX.509 client certificate iststronger than any user-defined password. Aber es muss geheim gehalten werden!

  • Mit einem Zertifikat sind dieidentity eines Clientsis well-known und leicht zu überprüfen.

  • Keine vergessenen Passwörter mehr!

Nachteile:

  • Sie müssen sich daran erinnern, dass für jeden Benutzer, der vom Server überprüft werden soll, sein Zertifikat in den konfiguriertentruststore installiert werden muss. Für kleine Anwendungen mit nur wenigen Clients kann dies möglicherweise praktikabel sein,with an increasing number of clients it may lead to complex key-management for users.

  • Der private Schlüssel eines Zertifikats muss in einer Client-Anwendung installiert sein. In der Tat:X.509 client authenticationis device dependent, was es unmöglich macht, diese Art der Authentifizierung in öffentlichen Bereichen zu verwenden, beispielsweise in einem Internetcafé.

  • Es muss einen Mechanismus geben, um gefährdete Client-Zertifikate zu widerrufen.

Um fortzufahren, ändern wir unsereX509AuthenticationServer so, dass sie sich vonWebSecurityConfigurerAdapter erstrecken und eine der bereitgestellten Konfigurationsmethoden überschreiben. Hier konfigurieren wir den Mechanismus vonx.509o, dass das FeldCommon Name (CN)eines Zertifikats zum Extrahieren von Benutzernamen analysiert wird.

Mit diesen extrahierten Benutzernamen suchtSpring Security in einem bereitgestelltenUserDetailsService nach übereinstimmenden Benutzern. Deshalb implementieren wir auch diese Service-Schnittstelle, die einen Demo-Benutzer enthält.

Tip: In Produktionsumgebungen kann diesesUserDetailsService seine Benutzer beispielsweise über einen Link laden: / spring-jdbc-jdbctemplate.

Sie müssen beachten, dass wir unsere Klasse mit@EnableWebSecurity und@EnableGlobalMethodSecurity mit aktivierter Vor- / Nachautorisierung versehen.

Mit letzterem können wir unsere Ressourcen mit@PreAuthorize und@PostAuthorize versehen, um eine differenzierte Zugriffskontrolle zu erhalten:

@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class X509AuthenticationServer extends WebSecurityConfigurerAdapter {
    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
          .and()
          .x509()
            .subjectPrincipalRegex("CN=(.*?)(?:,|$)")
            .userDetailsService(userDetailsService());
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) {
                if (username.equals("cid")) {
                    return new User(username, "",
                      AuthorityUtils
                        .commaSeparatedStringToAuthorityList("ROLE_USER"));
                }
            }
        };
    }
}

Wie bereits erwähnt, können wir jetztExpression-Based Access Control in unserem Controller verwenden. Insbesondere werden unsere Berechtigungsanmerkungen aufgrund der@EnableGlobalMethodSecurity-Annotation in unseren@Configuration: __ berücksichtigt

@Controller
public class UserController {
    @PreAuthorize("hasAuthority('ROLE_USER')")
    @RequestMapping(value = "/user")
    public String user(Model model, Principal principal) {
        ...
    }
}

Eine Übersicht über alle möglichen Berechtigungsoptionen finden Sie inofficial documentation.

Als letzten Änderungsschritt müssen wir der Anwendung mitteilen, wo sich unsertruststore befindet und dassSSL client authentication notwendig ist (server.ssl.client-auth=need).

Also setzen wir Folgendes in unsereapplication.properties:

server.ssl.trust-store=../keystore/truststore.jks
server.ssl.trust-store-password=${PASSWORD}
server.ssl.client-auth=need

Wenn wir nun die Anwendung ausführen und unseren Browser aufhttps://localhost:8443/user richten, werden wir darüber informiert, dass der Peer nicht verifiziert werden kann und das Öffnen unserer Website verweigert wird. Daher müssen wir auch unsereclient certificate installieren, die hier beispielhaft fürMozilla Firefox beschrieben werden:

  1. Geben Sieabout:preferences in die Adressleiste ein

  2. Öffnen SieAdvanced → View Certificates → Your Certificates

  3. Klicken Sie aufImport

  4. Suchen Sie den Ordnerexample tutorials und seinen Unterordnerspring-security-x509/keystore

  5. Wählen Sie die Dateicid.p12 aus und klicken Sie aufOK

  6. Geben Sie das Passwort für Ihr Zertifikat ein und klicken Sie aufOK

Als letzten Schritt aktualisieren wir unseren Browser-Tab mit der Website und wählen unser Client-Zertifikat im neu geöffneten Auswahldialog aus.

image

Wenn wir eine Willkommensnachricht wie“Hello cid!” sehen, waren wir erfolgreich!

5. Gegenseitige Authentifizierung mit XML

Das Hinzufügen vonX.509 client authentication zuhttp security configuration in XML ist ebenfalls möglich:


    ...
    

    
        
            
                
            
        
    
    ...

Um ein zugrunde liegendesTomcat zu konfigurieren, müssen wir unserekeystore und unseretruststore in den Ordnerconf legen und dieserver.xml bearbeiten:

Tip: WennclientAuth auf“want” eingestellt ist, istSSL weiterhin aktiviert, auch wenn der Client kein gültiges Zertifikat bereitstellt. In diesem Fall müssen wir jedoch einen zweiten Authentifizierungsmechanismus verwenden, beispielsweise ein Anmeldeformular, um auf die gesicherten Ressourcen zuzugreifen.

6. Fazit

In summary haben wir gelernt, wie man einkeystore erstellt, das eincertificate authority und einself-signed certificate for our development environment enthält.

Wir haben dietruststore containing a certificate authority and a client certificate erstellt und beideverify our server auf der Clientseiteand our client auf der Serverseite verwendet.

Wenn SieMakefile studiert haben, sollten Sie in der Lage sein,create certificates, make certificate-requests and import signed certificates mit Javakeytool zu verwenden.

Außerdem sollten Sie jetzt in der Lage sein,export a client certificate into the PKCS12 format zu verwenden und es in einer Clientanwendung wie einem Browser zu verwenden, z. B.Mozilla Firefox.

Und wir haben besprochen, wann es sinnvoll ist,Spring Security X.509 client authentication zu verwenden. Es liegt also an Ihnen, zu entscheiden, ob Sie es in Ihre Webanwendung implementieren oder nicht.

Zum Abschluss finden Sie den Quellcode zu diesem Artikelon Github.