[JAVA] Spring Security-Nutzungsnotiz Remember-Me

Grundlegende und systematische Geschichte Zertifizierungs- / Autorisierungsgeschichte CSRF-Geschichte Session Management Story Die Geschichte des Antwortheaders Method Security Story CORS-Geschichte Die Geschichte von Run-As Die Geschichte von ACL Teststory Sprechen Sie über die Zusammenarbeit mit MVC und Boot

Sonderedition Was Spring Security kann und was nicht

Was ist eine Remember-Me-Zertifizierung?

Ich schreibe oft "Angemeldet bleiben" oder "Angemeldet bleiben für ○ Wochen" auf dem Anmeldebildschirm von Webdiensten.

Hello World

Implementierung

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">

    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:remember-me />★ Jetzt denk dran-Ich ist aktiviert
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="hoge"
                    password="hoge"
                    authorities="" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().access("isAuthenticated()")
                .and()
                .formLogin()
                .and()
                .rememberMe(); //★ Denken Sie hier-Ermöglichen es mir
    }
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("hoge")
            .password("hoge")
            .authorities(Collections.emptyList());
    }
}

Funktionsprüfung

Wenn Sie den Anmeldebildschirm (/ login) öffnen, wird ein Kontrollkästchen mit dem Namen" Auf diesem Computer an mich erinnern "hinzugefügt (Standard-Anmeldebildschirm. 032ed0fa27a239bdc1cc #% E3% 83% AD% E3% 82% B0% E3% 82% A4% E3% 83% B3% E3% 83% 9A% E3% 83% BC% E3% 82% B8% E3% 82% 92 % E6% 8C% 87% E5% AE% 9A% E3% 81% 99% E3% 82% 8B) nur wenn Sie verwenden). Versuchen Sie zunächst, sich anzumelden, ohne es zu überprüfen.

spring-security.jpg

Überprüfen Sie nach dem Anmelden das Cookie Ihres Browsers.

spring-security.jpg

Die JSESSIONID wird gespeichert. Löschen Sie diese und zeichnen Sie den Bildschirm neu.

spring-security.jpg

Natürlich kehren Sie zum Anmeldebildschirm zurück.

Melden Sie sich anschließend mit dem Kontrollkästchen "Auf diesem Computer an mich erinnern" an. Aktivieren Sie auf dem Anmeldebildschirm das Kontrollkästchen.

spring-security.jpg

Wenn Sie sich das Cookie nach dem Anmelden ansehen, werden Sie feststellen, dass "JSESSIONID" und ein weiteres "Remember-Me" gespeichert sind.

spring-security.jpg

Löschen Sie "JSESSIONID" erneut und zeichnen Sie den Bildschirm neu.

spring-security.jpg

Anschließend kann der Bildschirm neu gezeichnet werden, ohne zum Anmeldebildschirm übersprungen zu werden. Wenn Sie sich das Cookie ansehen, wird "JSESSIONID" mit einem anderen Wert als zuvor gespeichert.

Wie es funktioniert

--Remember-Me wird beim Anmelden aktiviert, wenn den Anmeldeparametern ein Parameter mit dem Namen "Remember-Me" hinzugefügt wird

spring-security.jpg

Über KEY

Der zum Signieren verwendete SCHLÜSSEL zeigt auf eine beliebige Zeichenfolge, die im Attribut "key" von "" in der Konfigurationsdatei angegeben werden kann.

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        ...
        <sec:remember-me key="foobar" />
    </sec:http>
    
    ...
</beans>

Dieses Attribut ist jedoch optional, andernfalls wird eine zufällige Zeichenfolge verwendet, die mit "SecureRandom" generiert wurde.

Ich denke, es ist sicherer, "SecureRandom" zu verwenden, aber dieser Wert wird nur einmal generiert, wenn die Anwendung gestartet wird. Wenn Sie also die Anwendung neu starten, während Sie "SecureRandom" verwenden, werden alle vom Client aufgezeichneten "Remember-Me" -Cookies ungültig. (Da sich der Signaturwert ändert, wenn sich der SCHLÜSSEL ändert, tritt beim Überprüfen der Signatur immer ein Fehler auf.)

Es scheint, dass Sie eine feste Zeichenfolge angeben müssen, wenn Sie das "Remember-Me" -Cookie des Clients beibehalten möchten, auch wenn Sie die Anwendung neu starten.

Vorsichtsmaßnahmen bei Verwendung des Standard-Remember-Me

――Wenn Sie den Wert von Cookie kennen, können Sie aufgrund des oben genannten Mechanismus leicht fälschen.

Was Sie tun sollten, wenn Sie es ernsthaft verwenden

Aktivieren Sie das sichere Attribut des Cookies

Wenn Sie das sichere Attribut des Cookies aktivieren, wird das Cookie nur für die https-Kommunikation gesendet. Wenn Sie ein Cookie über eine unverschlüsselte http-Kommunikation senden, wird es möglicherweise von einem Dritten abgefangen und das Cookie wird möglicherweise gestohlen. Daher sollte diese Einstellung aktiviert sein.

Wenn Sie Spring Securty verwenden, können Sie das sichere Attribut des von Remember-Me verwendeten Cookies aktivieren, indem Sie Folgendes festlegen:

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        ...
        <sec:remember-me use-secure-cookie="true" />
    </sec:http>
    
    ...
</beans>

Setzen Sie das Attribut "use-secure-cookie" des Tags "" auf "true".

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .useSecureCookie(true);
    }
    
    ...
}

Setze useSecureCookie (true).

Lassen Sie keine wichtige Verarbeitung zu, wenn Sie sich mit Remember-Me anmelden

Vertrauen Sie der Remember-Me-Anmeldung nicht vollständig und benötigen Sie vor einem wirklich wichtigen Vorgang erneut eine Kennwortauthentifizierung. Eine wichtige Verarbeitung umfasst beispielsweise das Aktualisieren von Daten oder den Zugriff auf eine Seite mit persönlichen Informationen.

Selbst wenn das Remember-Me-Cookie gestohlen und gefälscht wird, können Sie es auf diese Weise davor schützen, wirklich wichtige Aktionen auszuführen.

Ich denke, das ist derjenige, der oft nach einem Passwort fragt, bevor er eine Bestellung auf einer Online-Shopping-Site bestätigt (wahrscheinlich).

Zugriffssteuerungsausdrücke für Spring Security (http://qiita.com/opengl-8080/items/032ed0fa27a239bdc1cc#%E5%BC%8F%E3%83%99%E3%83%BC%E3% 82% B9% E3% 81% A7% E3% 81% AE% E3% 82% A2% E3% 82% AF% E3% 82% BB% E3% 82% B9% E5% 88% B6% E5% BE% In A1) können Sie einen Ausdruck verwenden, der berücksichtigt, dass es sich nicht um Remember-Me handelt, z. B. "isFullyAuthenticated ()", sodass er mithilfe dieses Ausdrucks realisiert werden kann.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/remember-me/high-level" access="isFullyAuthenticated()" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        ...
        <sec:remember-me />
    </sec:http>
    
    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/remember-me/high-level").fullyAuthenticated()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe();
    }
    
    ...
}

Es ist so eingestellt, dass Sie beim Zugriff auf "/ memor-me / high-level" vollständig authentifiziert sein müssen ("fullAuthenticated ()").

Außerdem haben wir ein einfaches Servlet vorbereitet, das beim Zugriff auf / memor-me / * nur den Pfad zu diesem Zeitpunkt zurückgibt.

** Funktionsprüfung **

spring-security.jpg

Melden Sie sich mit aktiviertem Remember-Me an.

spring-security.jpg

Entfernen Sie "JSESSIONID" aus dem Cookie (machen Sie es wie eine tote Sitzung).

Wenn Sie in diesem Zustand erneut auf die Startseite zugreifen, wird die automatische Anmeldung von Remember-Me ausgeführt und die Startseite wird angezeigt.

Greifen Sie auf / memor-me / foo zu, nachdem Sie sich mit Remember-Me angemeldet haben.

spring-security.jpg

Die Seite wird normal angezeigt. Dann gehe zu "/ Remember-Me / High-Level".

spring-security.jpg

Dieses Mal werden Sie zur Anmeldeseite weitergeleitet. Dies liegt daran, dass "/ memor-me / high-level" auf "vollständig authentifiziert" eingestellt ist, dh nur eine vollständige Anmeldung mit einem Kennwort angezeigt werden kann.

Geben Sie Ihr Passwort ein, um sich anzumelden.

spring-security.jpg

Dieses Mal wird "/ memor-me / high-level" richtig angezeigt.

Spring Security steuert das Übergangsziel nach der Anmeldung automatisch als die URL, auf die Sie vor der Anmeldung zugreifen wollten. Daher sind keine besonderen Einstellungen erforderlich (es kann eine beliebige URL angegeben werden).

Stellen Sie fest, dass ein Cookie gestohlen wurde

Mit dem oben beschriebenen Standard-Remember-Me-Mechanismus kann nicht festgestellt werden, ob ein Cookie von einem Dritten gestohlen wurde. Daher bemerkt das Opfer nicht, dass es beschädigt wurde, und gibt dem Angreifer einen Spielraum, um zu tun, was er will.

Daher bietet Spring Security einen Mechanismus, der erkennen kann, ob ein Cookie gestohlen wurde, um den Schaden zu minimieren.

Mechanismus zur Erkennung gestohlener

Spring Security realisiert den Diebstahlerkennungsmechanismus, indem es den im Artikel hier erläuterten Mechanismus übernimmt.

Der Umgang mit Cookies ist ungefähr wie folgt.

spring-security.jpg

Der Inhalt des Cookies ist "Serie" und "Token". Und der Server zeichnet die Kombination der beiden auf.

Zum Zeitpunkt der automatischen Anmeldung wird die aus dem Cookie extrahierte "Serie" nach dem vom Server aufgezeichneten "Token" durchsucht und überprüft, ob es mit dem "Token" im Cookie übereinstimmt.

Die automatische Anmeldung wird nur durchgeführt, wenn die "Token" übereinstimmen. Danach werden die "Token" durch neue Werte ersetzt.

Dieser Mechanismus zur Verwendung der "Serie", bei der Werte als Kennung zur Identifizierung des Cookies wiederverwendet werden, und zur Aktualisierung des "Tokens" bei jeder automatischen Anmeldung ist ein Mechanismus zur Erkennung von Diebstahl.

Wenn sich ein Angreifer automatisch mit einem gestohlenen Cookie anmeldet, werden das im Cookie des Angreifers enthaltene "Token" und das vom Server aufgezeichnete "Token" aktualisiert, aber das "Token" des Cookies des Opfers wird aktualisiert. Wird alt bleiben.

Wenn das Opfer versucht, sich nach einer nicht autorisierten Anmeldung automatisch anzumelden, stimmen das auf der Serverseite aufgezeichnete "Token" und das im Cookie des Opfers enthaltene "Token" nicht überein.

spring-security.jpg

Auf diese Weise kann der Server erkennen, dass das Cookie möglicherweise gestohlen wurde, und das Opfer oder den Dienstadministrator benachrichtigen.

Dies ist meine persönliche Meinung, aber ich bin der Meinung, dass der Diebstahl umso schneller erkannt werden kann, je kürzer das Sitzungszeitlimit ist. In diesem Fall treten jedoch häufig Sitzungszeitlimits auf, und Sie müssen das Kennwort jedes Mal eingeben, wenn Sie versuchen, einen Bildschirm zu öffnen, für den eine vollständige Anmeldung erforderlich ist, wie oben beschrieben. Ich bin der Meinung, dass die Benutzerfreundlichkeit abnimmt. (Dies hängt davon ab, ob Sie der Sicherheit oder der Benutzerfreundlichkeit Priorität einräumen.)

Zufällige Zeichenketten, die mit "SecureRandom" generiert wurden, werden für "Serien" und "Token" verwendet.

Aktivieren Sie den Diebstahlerkennungsmechanismus in Spring Security

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    compile 'org.springframework:spring-jdbc:4.3.7.RELEASE' ★
}

Spring-jdbc zu Abhängigkeiten hinzugefügt.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>
    
    ...
    
    <bean id="rememberMeTokenRepository"
          class="org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl" />
    
    <sec:http>
        ...
        <sec:remember-me token-repository-ref="rememberMeTokenRepository" />
    </sec:http>
    
    ...
</beans>

Fügen Sie der Bean-Definition "InMemoryTokenRepositoryImpl" hinzu und geben Sie es in "token-repository-ref" des Tags "" an.

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;

import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/remember-me/high-level").fullyAuthenticated()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .tokenRepository(new InMemoryTokenRepositoryImpl()); ★
    }
    
    ...
}

Übergeben Sie eine Instanz von "InMemoryTokenRepositoryImpl" mit "tokenRepository ()".

spring-security.jpg

Melden Sie sich mit aktiviertem Remember-Me an.

spring-security.jpg

Kopieren Sie den Wert des ausgegebenen Cookies.

spring-security.jpg

Öffnen Sie einen anderen Browser und fügen Sie dem Cookie "Remember-Me" hinzu, um den gerade kopierten Wert festzulegen.

spring-security.jpg

Wenn Sie auf die oberste Seite zugreifen, können Sie sich ohne Eingabe eines Kennworts anmelden (bei einem erfolgreichen Angriff).

Kehren Sie in diesem Zustand zu dem Browser zurück, der ursprünglich mit dem Kennwort normal angemeldet war, löschen Sie "JSESSIONID" und greifen Sie dann auf die Startseite zu. (Reproduktion des Zustands, auf den das Opfer nach Ablauf der Sitzung erneut zugegriffen hat)

spring-security.jpg

CookieTheftException wird ausgelöst und ein Fehlerbildschirm wird angezeigt.

Selbst wenn eine Ausnahme, die Cookie-Diebstahl bedeutet, ausgelöst wird, scheint sie standardmäßig nicht behandelt zu werden und wird als Systemfehler behandelt. (Vorerst wurde festgestellt, dass der Cookie gestohlen wurde.)

Klassen, die erscheinen

spring-security.png

Der Remember-Me-Prozess wird von "RememberMeAuthenticationFilter" gestartet. Wenn im nicht authentifizierten Zustand Zugriff besteht, delegiert dieser Filter den Authentifizierungsprozess an "RememberMeService".

RememberMeService hat zwei Implementierungsklassen. TokenBasedRememberMeServices bietet eine Remember-Me-Authentifizierung mit der einfachen Methode, die wir in der ersten Hello World gesehen haben. Auf der anderen Seite realisiert "PersistentTokenBasedRememberMeServices" Remember-Me durch eine Methode, die Diebstahl erkennen kann, die später beschrieben wird.

PersistentTokenBasedRememberMeServices delegiert die Speicherung von" Serien "und" Token "an PersistentTokenRepository, und PersistentTokenRepository hat abhängig von der spezifischen Speichermethode zwei Klassen. JdbcTokenRepositoryImpl zeichnet Informationen in einer Tabelle in der Datenbank auf und InMemoryTokenRepositoryImpl zeichnet sie im Speicher auf.

Wenn Sie nur Remember-Me aktivieren, wird "TokenBasedRememberMeServices" verwendet, um "RememberMeService" zu implementieren. Sie können jedoch die Implementierung von "RememberMeService" auf "PersistentTokenBasedRememberMeServices" umstellen, indem Sie "PersistentTokenRepository" in "Token-Repository-Ref" angeben.

Fehlerbehandlung beim Erkennen von Cookie-Diebstahl

Eine "CookieTheftException" wird ausgelöst, wenn ein Cookie-Diebstahl erkannt wird. Wenn Sie jedoch versuchen, diese Ausnahme zu behandeln, scheint dies mit der von Spring Security bereitgestellten API nicht möglich zu sein.

Die von "PersistentTokenBasedRememberMeServices" ausgelöste "CookieTheftException" wird einmal von "AbstractRememberMeServices" abgefangen. Nachdem der Cookie gelöscht wurde, wird er erneut geworfen.

Danach wird es nirgendwo gefangen und fliegt zum Servlet.

Wenn Sie versuchen, diese Ausnahme zu behandeln, haben Sie keine andere Wahl, als den Standard-Ausnahmebehandlungsmechanismus für Servlets zu verwenden.

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    
    ...
    
    <error-page>
        <exception-type>org.springframework.security.web.authentication.rememberme.CookieTheftException</exception-type>
        <location>/cookie-theft.html</location>
    </error-page>
</web-app>

cookie-theft.html


<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>CookieTheftException</title>
    </head>
    <body>
        <h1>Der Keks wurde gestohlen!</h1>
    </body>
</html>

Wenn Sie so arbeiten, dass "CookieTheftException" ausgelöst wird, wird der Fehlerbildschirm der Stapelverfolgung nicht angezeigt und Sie werden zum nächsten Bildschirm übersprungen.

spring-security.jpg

Servlet kann das Übergangsziel definieren, wenn in web.xml ein Fehler mit dem Tag <Fehlerseite> auftritt. Verwenden Sie dies also. Im obigen Beispiel können nur statische Seiten angezeigt werden, aber die dynamische Verarbeitung kann durch Kombination mit Servlet eingefügt werden.

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
    
    ...
    
    <error-page>
        <exception-type>org.springframework.security.web.authentication.rememberme.CookieTheftException</exception-type>
        <location>/cookie-theft</location>
    </error-page>
</web-app>

CookieTheftServlet.java


package sample.spring.security.servlet;

import org.springframework.security.web.authentication.rememberme.CookieTheftException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/cookie-theft")
public class CookieTheftServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        CookieTheftException e = (CookieTheftException)req.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
        try (PrintWriter writer = resp.getWriter()) {
            writer.println(e.getMessage());
        }
    }
}

Geben Sie an, wann ein Fehler generiert wird spring-security.jpg

Stellen Sie sicher, dass das Servlet den durch "" von "" angegebenen Pfad akzeptiert. In diesem Servlet können Sie mit getAttribute () auf Fehlerinformationen wie Ausnahmeobjekte aus HttpServletRequest verweisen.

Ich habe es nicht ausprobiert, aber wenn Sie Spring MVC verwenden, können Sie es vom MVC-Controller akzeptieren lassen.

In jedem Fall können Sie so eine beliebige Verarbeitung durchführen, sodass Sie Fehlerinformationen per E-Mail senden können.

In Datenbank speichern

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    compile 'org.springframework:spring-jdbc:4.3.7.RELEASE'
    compile 'com.h2database:h2:1.4.193'
}

Verwenden Sie für die Datenbank vorerst H2 der integrierten Datenbank.

src/main/resources/sql/create_remember-me_tables.sql


CREATE TABLE PERSISTENT_LOGINS (
    USERNAME  VARCHAR(64) NOT NULL,
    SERIES    VARCHAR(64) NOT NULL PRIMARY KEY,
    TOKEN     VARCHAR(64) NOT NULL,
    LAST_USED TIMESTAMP   NOT NULL
);

Eine SQL-Datei, die eine Tabelle zum Aufzeichnen von Token-Informationen erstellt.

namespace

applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       ...
       xsi:schemaLocation="
         ...
         http://www.springframework.org/schema/jdbc
         http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
    
    ...
    
    <jdbc:embedded-database id="dataSource" type="H2">
        <jdbc:script location="classpath:/sql/create_remember-me_tables.sql" />
    </jdbc:embedded-database>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/remember-me/high-level" access="isFullyAuthenticated()" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:remember-me data-source-ref="dataSource" />
    </sec:http>
    
    ...
</beans>

Definieren Sie die Datenquelle als Bean und geben Sie sie im Attribut "data-source-ref" des Tags "" an.

Java Configuration

python


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;
import java.util.Collections;

@EnableWebSecurity
@ComponentScan
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .rememberMe()
                .tokenRepository(this.createTokenRepository());
    }
    
    public PersistentTokenRepository createTokenRepository() {
        DataSource dataSource =
                new EmbeddedDatabaseBuilder()
                    .generateUniqueName(true)
                    .setType(EmbeddedDatabaseType.H2)
                    .setScriptEncoding("UTF-8")
                    .addScript("/sql/create_remember-me_tables.sql")
                    .build();

        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        
        return tokenRepository;
    }
    
    ...
}

Die Java-Konfiguration scheint keine Methode zu haben, um "DataSource" direkt anzugeben. Setzen Sie "DataSource" auf "JdbcTokenRepositoryImpl" und übergeben Sie sie dann mit der Methode "tokenRepository ()".

Passen Sie die Tabelle an, in der Token gespeichert sind

Wie ich die Implementierung gesehen habe, scheint es unmöglich, den Tabellennamen und den Spaltennamen nur mit der Standardimplementierung anzupassen. Die Implementierung von JdbcTokenRepositoryImpl sieht folgendermaßen aus:

JdbcTokenRepositoryImpl.java


public class JdbcTokenRepositoryImpl extends JdbcDaoSupport implements
		PersistentTokenRepository {
	// ~ Static fields/initializers
	// =====================================================================================

	/** Default SQL for creating the database table to store the tokens */
	public static final String CREATE_TABLE_SQL = "create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, "
			+ "token varchar(64) not null, last_used timestamp not null)";
	/** The default SQL used by the <tt>getTokenBySeries</tt> query */
	public static final String DEF_TOKEN_BY_SERIES_SQL = "select username,series,token,last_used from persistent_logins where series = ?";
	/** The default SQL used by <tt>createNewToken</tt> */
	public static final String DEF_INSERT_TOKEN_SQL = "insert into persistent_logins (username, series, token, last_used) values(?,?,?,?)";
	/** The default SQL used by <tt>updateToken</tt> */
	public static final String DEF_UPDATE_TOKEN_SQL = "update persistent_logins set token = ?, last_used = ? where series = ?";
	/** The default SQL used by <tt>removeUserTokens</tt> */
	public static final String DEF_REMOVE_USER_TOKENS_SQL = "delete from persistent_logins where username = ?";

	// ~ Instance fields
	// ================================================================================================

	private String tokensBySeriesSql = DEF_TOKEN_BY_SERIES_SQL;
	private String insertTokenSql = DEF_INSERT_TOKEN_SQL;
	private String updateTokenSql = DEF_UPDATE_TOKEN_SQL;
	private String removeUserTokensSql = DEF_REMOVE_USER_TOKENS_SQL;

        ...

SQL-Text wird im Feld public`` static definiert und bei der Instanziierung in das Feld gesetzt. Das in diesem Feld festgelegte SQL wird bei der Suche nach Token usw. verwendet, es gibt jedoch keine Methode zum Umschreiben dieses Felds. Es scheint also, dass es nicht umgeschrieben werden kann (ernsthaft? Stimmt etwas nicht?).

Wenn Sie den Tabellennamen oder Spaltennamen aufgrund von Umständen für Erwachsene nicht angeben können, müssen Sie möglicherweise "JdbcTokenRepositoryImpl" kopieren, um Ihr eigenes "TokenRepository" zu erstellen.

Referenz

Recommended Posts

Spring Security-Nutzungsnotiz Remember-Me
Spring Security-Nutzungsnotiz CSRF
Spring Security-Nutzungsnotiz Run-As
Sicherheit der Verwendungsnotizmethode für Spring Security
Spring Security-Nutzungsnotiz CORS
Spring Security-Verwendungsnotiztest
Spring Security-Nutzungsnotiz Authentifizierung / Autorisierung
Antwortheader für die Verwendung von Spring Security
Sitzungsverwaltung für Spring Security-Nutzungsnotizen
Spring Security-Nutzungsnotiz Basic / Mechanismus
Spring Security Usage Memo Domänenobjektsicherheit (ACL)
Hinweise zur Verwendung von Spring Shell
Verwendungshinweise zu JavaParser
Hinweise zur Verwendung von WatchService
PlantUML-Nutzungsnotiz
Verwendungshinweise zu JUnit5
JJUG CCC Frühjahr 2018 Memo
Informationen zur Spring Security-Authentifizierung
Schreiben von Frühlingsstiefel-Memos (1)
Spring Security erhöht 403 verboten
Schreiben von Spring Boot-Memos (2)
[Persönliche Notizen] Über das Spring Framework
JJUG CCC 2018 Frühlingsbeteiligungsprotokoll
Spring Framework Selbststudium Memo series_1
Anmeldefunktion mit Spring Security
[Frühlingssicherheit] Frühlingssicherheit auf GAE (SE)
Hinweise zur Verwendung des Abhängigkeitsmanagement-Plugins
Versuchen Sie es mit Spring Boot Security
Memo zur Spring Boot Controller-Methode
Implementierte Authentifizierungsfunktion mit Spring Security ②
◆ Konstruktionsnotiz für Spring Boot + Gradle-Umgebung
JCA-Verwendungsprotokoll (Java Encryption Architecture)
Implementierte Authentifizierungsfunktion mit Spring Security ③
Spring Boot Tutorial Verwenden der Spring Security-Authentifizierung
Frühlingsrahmen Einfaches Studienmemo (2): AOP
Implementierte Authentifizierungsfunktion mit Spring Security ①
Erfahren Sie mehr über die Architektur der Spring Security-Authentifizierungsverarbeitung
Memo nach dem ersten Frühjahrsprojekt-MVC-
Ein Memo, das Spring Boot berührte
Frühjahr gründliche Einführung Version Upgrade Memo
Zertifizierung / Autorisierung mit Spring Security & Thymeleaf
Memo nach dem ersten Frühjahrsprojekt-Datenbank-
Verwendung von Thymeleaf mit Spring Boot
Spring 5 MVC-Webanwendungsentwicklung mit Visual Studio Code Spring Security-Nutzung 1/3 [Vorbereitung]