Tutorial Spring Security

Tutorial Spring Security: Kapitel 4 – Default Schutz durch Spring Security

Als Basis hierfür dient das Projekt aus dem Beitrag JPA und Spring Security. Den Source Code zu diesem Tutorial findet ihr auf dem Micromata Github Bereich.

Viel Spaß beim Lesen dieses Tutorials-Beitrags.

CSRF

Schauen wir uns beispielsweise das HTML unserer Login Form an:

<form name="f" method="post" action="/login">
    <fieldset>
        <legend>Please Login</legend>
            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" />
            </div>
            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" name="password" />
            </div>
            <button type="submit" class="btn btn-primary">Log in</button>
    </fieldset>
    <input type="hidden" name="_csrf" value="b1f1cfe2-56b4-407b-8b53-5764701c2199" />
</form>

Hier sieht man bereits eines dieser per Default aktiven Sicherheitsmechanismen. Bei dem Hidden Field mit dem Namen _csrf handelt es sich um einen CSRF-Token zum Schutz vor Cross-Site-Request-Forgery-Angriffen (CSRF).

Security Headers

Neben dem CSRF-Token bietet Spring Security diverse Security Header, die in die Response eingefügt werden und in der WebSecurityConfig durch den Aufruf von http.headers().defaultsDisabled() deaktiviert werden können. Nachfolgend ist diese Methode zu sehen:

public HeadersConfigurer<H> defaultsDisabled() {
    contentTypeOptions.disable();
    xssProtection.disable();
    cacheControl.disable();
    hsts.disable();
    frameOptions.disable();
    return this;
}

Die einzelnen Felder haben dabei folgenden Inhalt:

Feld Header Wert
contentTypeOptions X-Content-Type-Options nosniff
xssProtection X-XSS-Protection 1; mode=block
cacheControl Cache-Control no-cache, no-store, max-age=0, must-revalidate
cacheControl Pragma no-cache
cacheControl Expires 0
hsts Strict-Transport-Security max-age=31536000 ; includeSubDomains
frameOptions X-Frame-Options DENY

Der HSTS-Eintrag ist nur dann im Header zu finden, wenn die Applikation unter HTTPS aufgerufen wird. Wie dies mit einer Spring Boot Applikation gemacht wird, wird im noch ausstehenden Beitrag HTTPS mit Spring Boot erklärt.

Aktivierung der H2 Console

Um die in Spring Boot integrierte H2 Console aufrufen zu können, genügt es diese in der Konfigurationsdatei der Applikation einzutragen. Die Konfigurationsdatei ist dabei unter /resources/application.properties oder /resources/application.yml zu finden. Welche Dateiendung gewählt wird, ist Geschmacksache und beeinflusst die spätere Notation der Konfiguration.

application.properties

spring.datasource.url=jdbc:h2:mem:mydb
spring.h2.console.enabled=true
spring.h2.console.path=/console

application.yml

spring:
    datasource.url: jdbc:h2:mem:mydb
    h2.console:
        enabled: true
        path: /console

Nach einem Aufruf von /console sollte nun die H2 Console erscheinen:Spring Security H2-Console

CSRF Ausnahmen

Bei einem Klick auf Connect erscheint jedoch die folgende Fehlerseite:Spring Security csrfError

Damit wir uns in die H2 Console einloggen können, müssen wir den CSRF Sicherheitsmechanismus für /console deaktivieren.

Dazu wird die WebSecurityConfig angepasst:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/noSecurity").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login").permitAll()
        .and().logout().permitAll();
 
    http.csrf().ignoringAntMatchers("/console/**");
}

Durch http.csrf().ignoringAntMatchers("/console/**") erreichen wir genau dieses Verhalten. Alles unter /console/* wird nun nicht mehr auf ein CSRF-Token überprüft.

Frame Options Anpassung

Klicken wir nun auf Connect in der H2 Console, dann sehen wir nichts. Die Console des Chrome zeigt jedoch folgendes:

Spring Security Chrome
Diesen Fehler erhalten wir, da die H2 Console in einem Frame läuft und das durch die Security Headers per Default verboten wird.
Aus diesem Grund müssen die Headers angepasst und die X-Frame-Options von Deny auf SAMEORIGIN gesetzt werden.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/noSecurity").permitAll()
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login").permitAll()
        .and().logout().permitAll();

    http.csrf().ignoringAntMatchers("/console/**")
        .and().headers().frameOptions().sameOrigin();
}

Nun können wir uns erfolgreich in die H2 Console einloggen.

Jürgen Fast

Softwareentwickler