[JAVA] Spring Security-Nutzungsnotiz Authentifizierung / Autorisierung

Grundlegende und systematische Geschichte Remember-Me-Geschichte 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

Authentifizierung

UserDetailsService: Benutzerinformationen suchen

UserDetailsService ist für das Abrufen von Benutzerinformationen verantwortlich.

Spring Security bietet mehrere Klassen, die "UserDetailsService" implementieren.

In Erinnerung

Implementierung, die Benutzerinformationen im Speicher speichert. Die spezifische Klasse ist "InMemoryUserDetailsManager".

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"
       ...>

    ...

    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user name="hoge" password="HOGE" authorities="ROLE_USER" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

--Erläutern Sie die Tags "" und "".

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
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;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ...
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("hoge").password("HOGE").roles("USER");
    }
}

JDBC Eine Implementierung, die Benutzerinformationen aus der Datenbank abruft. Die eigentliche Klasse ist "JdbcUserDetailsManager".

** Verbreitet **

build.Gradle (zusätzliche Abhängigkeit)


    compile 'org.springframework:spring-jdbc:4.3.6.RELEASE'
    compile 'com.h2database:h2:1.4.193'

src/main/resources/sql/create_database.sql


CREATE TABLE USERS (
    USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
    PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,
    ENABLED  BOOLEAN NOT NULL
);

CREATE TABLE AUTHORITIES (
    USERNAME  VARCHAR_IGNORECASE(50) NOT NULL,
    AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,
    CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY (USERNAME) REFERENCES USERS(USERNAME),
    CONSTRAINT UK_AUTHORITIES UNIQUE (USERNAME, AUTHORITY)
);

INSERT INTO USERS VALUES ('fuga', 'FUGA', true);
INSERT INTO AUTHORITIES VALUES ('fuga', 'USER');

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"
       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_database.sql" />
    </jdbc:embedded-database>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:jdbc-user-service data-source-ref="dataSource"  />
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

--Verwenden Sie das Tag "".

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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 javax.sql.DataSource;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ...
    }
    
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
                .generateUniqueName(true)
                .setType(EmbeddedDatabaseType.H2)
                .setScriptEncoding("UTF-8")
                .addScript("/sql/create_database.sql")
                .build();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }
}

--Verwenden Sie die Methode "jdbcAuthentication ()" von "AuthenticationManagerBuilder".

Passen Sie die Tabellen- und Spaltennamen an

CREATE TABLE USERS (
    LOGIN_ID VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,
    PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,
    ENABLED  BOOLEAN NOT NULL
);

CREATE TABLE AUTHORITIES (
    LOGIN_ID  VARCHAR_IGNORECASE(50) NOT NULL,
    ROLE VARCHAR_IGNORECASE(50) NOT NULL,
    CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY (LOGIN_ID) REFERENCES USERS(LOGIN_ID),
    CONSTRAINT UK_AUTHORITIES UNIQUE (LOGIN_ID, ROLE)
);

Versuchen Sie, "USERNAME" in "LOGIN_ID" und "AUTHORITY" in "ROLE" zu ändern.

Wenn Sie den Tabellennamen oder den Spaltennamen nach Belieben ändern möchten, passen Sie die SQL an, wenn Sie nach Benutzerinformationen suchen. Der Spaltenname kann beliebig lang sein, solange die Reihenfolge der Elemente zum Zeitpunkt der Suche übereinstimmt.

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"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       ...>

    ...
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:jdbc-user-service
                data-source-ref="dataSource"
                users-by-username-query="SELECT LOGIN_ID, PASSWORD, ENABLED FROM USERS WHERE LOGIN_ID=?"
                authorities-by-username-query="SELECT LOGIN_ID, ROLE FROM AUTHORITIES WHERE LOGIN_ID=?" />
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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 javax.sql.DataSource;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ...
    }
    
    @Bean
    public DataSource dataSource() {
        ...
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery("SELECT LOGIN_ID, PASSWORD, ENABLED FROM USERS WHERE LOGIN_ID=?")
        .authoritiesByUsernameQuery("SELECT LOGIN_ID, ROLE FROM AUTHORITIES WHERE LOGIN_ID=?");
    }
}

Erstellen Sie Ihren eigenen UserDetailsService

MyUserDetailsService.java


package sample.spring.security;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if ("hoge".equals(username)) {
            return new User(username, "HOGE", AuthorityUtils.createAuthorityList("USER"));
        }
        
        throw new UsernameNotFoundException("not found : " + username);
    }
}

--Erstellen Sie eine Klasse, die "UserDetailsService" implementiert.

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="myUserDetailsService" class="sample.spring.security.MyUserDetailsService" />
    
    <sec:authentication-manager>
        <sec:authentication-provider user-service-ref="myUserDetailsService" />
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
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;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    ...
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new MyUserDetailsService());
    }
}

Passwort-Hashing

Warum Hashing benötigt wird

In dem unwahrscheinlichen Fall, dass Daten verloren gehen, ist es schlecht bedingt, dass das Passwort im Klartext gespeichert wird.

Daher wird das Kennwort normalerweise in einer Datenbank oder dergleichen in einer Form gespeichert, in der die ursprüngliche Zeichenfolge nicht angegeben werden kann. Wenn Sie keine Kennwörter kombinieren müssen, verwenden Sie eine Hash-Funktion, um das Kennwort zu konvertieren.

BCrypt Apropos Hash-Funktionen, es gibt MD5 und SHA, aber wenn Sie Hash-Passwörter verwenden möchten, scheint es besser, BCrypt zu verwenden.

Wenn Sie die Hash-Funktion einfach einmal anwenden, [Passwortangriff] wie Round-Robin-Angriff, Wörterbuchangriff, Regenbogentabelle usw. (https://ja.wikipedia.org/wiki/%E3%83%91%E3% 82% B9% E3% 83% AF% E3% 83% BC% E3% 83% 89% E3% 82% AF% E3% 83% A9% E3% 83% 83% E3% 82% AF) werden.

BCrypt macht es schwierig, das ursprüngliche Passwort zu erraten, indem zufälliges Salz angewendet und dann mehrmals Hashing angewendet wird, anstatt die Eingabe einfach einmal zu haschen.

Spring Security empfiehlt außerdem die Verwendung dieses BCrypt.

Implementierung

Passwort-Hashing kann erreicht werden, indem "PasswordEncoder" auf "DaoAuthenticationProvider" gesetzt wird. Verwenden Sie bei Verwendung von BCrypt die PasswordEncoder-Implementierung`` BCryptPasswordEncoder`.

Darüber hinaus wird der Hash-Wert im Voraus durch BCrypt-Hashwert-Berechnung | tekboy beschrieben.

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="passwordEncoder"
          class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="hoge"
                    password="$2a$08$CekzJRYhb5bzp5mx/eZmX.grG92fRXo267QVVyRs0IE.V.zeCIw8S"
                    authorities="ROLE_USER" />
            </sec:user-service>
            
            <sec:password-encoder ref="passwordEncoder" />
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    ...
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth, PasswordEncoder passwordEncoder) throws Exception {
        auth.inMemoryAuthentication()
            .passwordEncoder(passwordEncoder)
            .withUser("hoge")
            .password("$2a$08$CekzJRYhb5bzp5mx/eZmX.grG92fRXo267QVVyRs0IE.V.zeCIw8S")
            .roles("USER");
    }
}

Codieren Sie das Passwort

Um ein Passwort zu kodieren, nehmen Sie "PasswordEncoder" aus dem Container und verwenden Sie die Methode "encode ()".

EncodePasswordServlet.java


package sample.spring.security.servlet;

import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

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;

@WebServlet("/encode-password")
public class EncodePasswordServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(req.getServletContext());
        PasswordEncoder passwordEncoder = context.getBean(PasswordEncoder.class);

        String password = req.getParameter("password");
        String encode = passwordEncoder.encode(password);
        System.out.println(encode);
    }
}

Greifen Sie nach dem Anmelden auf http: // localhost: 8080 / xxxx / encode-password? Password = fuga zu (ersetzen Sie den Kontextpfad entsprechend).

Ausgabe der Serverkonsole


$2a$10$2qVDkAqxp8eDrxR8Be2ZpubYGOCVZ7Qy9uK/XzOIY1ZoxpChtrWDK

Authentication "Authentifizierung" existiert in einer der wichtigen Klassen, aus denen Spring Security besteht. Diese Klasse speichert Informationen zu authentifizierten Benutzern (z. B. Benutzernamen und eine Liste der erteilten Berechtigungen).

Wenn die Authentifizierung mit "AuthenticationProvider" erfolgreich ist, erstellt "AuthenticationProvider" ein authentifiziertes "Authentication" -Objekt und gibt es zurück ("isAuthenticated ()" gibt "true" zurück). Danach wird auf dieses authentifizierte "Authentifizierungs" -Objekt bei der nachfolgenden Verarbeitung wie der Berechtigungsprüfung verwiesen.

So erhalten Sie Authentifizierung und verfügbare Informationen

SecurityContextHolderSampleServlet.java


package sample.spring.security.servlet;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

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 static java.util.stream.Collectors.*;

@WebServlet("/authentication")
public class SecurityContextHolderSampleServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("[authorities]");
        System.out.println("  " + auth.getAuthorities().stream()
                                    .map(GrantedAuthority::getAuthority)
                                    .collect(joining("\n  ")));

        WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
        System.out.println("[details]");
        System.out.println("  IP Address : " + details.getRemoteAddress());
        System.out.println("  Session ID : " + details.getSessionId());

        UserDetails principal = (UserDetails) auth.getPrincipal();
        System.out.println("[principal]");
        System.out.println("  username : " + principal.getUsername());
        System.out.println("  password : " + principal.getPassword());

        System.out.println("[credentials]");
        System.out.println("  " + auth.getCredentials());
    }
}

Ausführungsergebnis


[authorities]
  USER
[details]
  IP Address : 0:0:0:0:0:0:0:1
  Session ID : 0225051BCDFE2C34D55DF4FA9D9685C2
[principal]
  username : hoge
  password : null
[credentials]
  null

Aus Sicherheitsgründen werden die Kennwortinformationen nach erfolgreicher Anmeldung von AuthenticationManager (ProviderManager) explizit gelöscht (auf "null" gesetzt). Es ist auch möglich, es nicht mit der Option (eraseCredentialsAfterAuthentication) zu löschen.

Speicherort für die Authentifizierung

Authenticationの保存場所.png

Der "SecurityContext", der die "Authentifizierung" enthält, wird nach Abschluss der Authentifizierung standardmäßig in der "HttpSession" gespeichert.

Beim nächsten Zugriff in derselben Sitzung wird der in "HttpSession" gespeicherte "SecurityContext" abgerufen und in "SecurityContextHolder" gespeichert.

Dieser "SecurityContextHolder" verwendet standardmäßig "ThreadLocal", um "SecurityContext" im "statischen" Feld zu speichern. Daher kann der der aktuellen Anforderung zugeordnete "SecurityContext" global abgerufen werden.

Genau genommen enthält "SecurityContextHolder" eine Instanz von "SecurityContextHolderStrategy", und die Implementierung dieser Schnittstelle ist "ThreadLocalSecurityContextHolderStrategy", in der "SecurityContext" in "ThreadLocal" gespeichert ist.

Übrigens übernimmt "SecurityContextPersistenceFilter" das Laden und Entladen von "SecurityContext" in "SecurityContextHolder" und das Löschen von "ThreadLocal" für jede Anforderung.

Andere Speichermethode als ThreadLocal

Zusätzlich zu "ThreadLocalSecurityContextHolderStrategy" gibt es zwei verbleibende Klassen in der Implementierung von "SecurityContextHolderStrategy".

GlobalSecurityContextHolderStrategy

Speichern Sie nur einen "SecurityContext" in Ihrer Anwendung.

Diese Klasse wird beispielsweise in einer eigenständigen Anwendung verwendet. Bei eigenständigen Apps kann der laufende Benutzer der einzige Benutzer sein. In diesem Fall müssen Sie möglicherweise, selbst wenn Sie mehrere Threads erstellen, für alle dieselben Anmeldeinformationen verwenden.

InheritableThreadLocalSecurityContextHolderStrategy

Wenn ein neuer Thread erstellt wird, teilt er den "SecurityContext" des übergeordneten Threads.

Diese Klasse kann von mehreren Benutzern verwendet werden, wird jedoch verwendet, wenn bei der Verarbeitung jedes Benutzers ein neuer Thread erstellt wird, um die Hintergrundverarbeitung auszuführen. In diesem Fall werden die Threads getrennt, aber die Anmeldeinformationen müssen die Benutzerinformationen des übergeordneten Threads erben.

Welche Speichermethode verwendet wird, kann mit einer der folgenden Methoden geändert werden.

** In den Systemeigenschaften angegeben **

Sie kann angegeben werden, indem die Systemeigenschaft "spring.security.strategy" an die Startoptionen der JVM übergeben wird.

Bei der Angabe beim Starten von Tomcat


> set JAVA_OPTS=-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL

> cd %TOMCAT_HOME%\bin

> startup.bat

** Mit statischer Methode angeben **

python


SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);

SecurityContextHolder bietet eine Methode namens setStrategyName (String). Geben Sie für das Argument auch die in "SecurityContextHolder" definierte Konstante an.

Geben Sie die Anmeldeseite an

Wenn Sie die Formularanmeldung aktivieren, aber keine Anmeldeseite angeben, wird standardmäßig die von Spring Security generierte einfache Anmeldeseite verwendet.

spring-security.jpg

Dies ist nur ein Bildschirm zum Überprüfen des Vorgangs. In der tatsächlichen Anwendung muss dieser durch die von Ihnen erstellte Anmeldeseite ersetzt werden.

Ändern Sie die Anmeldeseite wie folgt.

Implementierung

my-login.jsp


<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>My Login Page</title>
    </head>
    <body>
        <h1>My Login Page</h1>
        
        <c:url var="loginUrl" value="/login" />
        <form action="${loginUrl}" method="post">
            <div>
                <label>Nutzername: <input type="text" name="username" /></label>
            </div>
            <div>
                <label>Passwort: <input type="password" name="password" /></label>
            </div>
            <input type="submit" value="login" />
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        </form>
    </body>
</html>

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="/my-login.jsp" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login login-page="/my-login.jsp" />
        <sec:logout />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/my-login.jsp").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/my-login.jsp");
    }

    ...
}

Funktionsprüfung

spring-security.jpg

Wenn Sie versuchen, auf eine Seite zuzugreifen, werden Sie zu Ihrer eigenen Anmeldeseite weitergeleitet.

Erläuterung

applicationContext.xml


        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/my-login.jsp" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login login-page="/my-login.jsp" />

my-login.jsp


        <c:url var="loginUrl" value="/login" />
        <form action="${loginUrl}" method="post">
            <div>
                <label>Nutzername: <input type="text" name="username" /></label>
            </div>
            <div>
                <label>Passwort: <input type="password" name="password" /></label>
            </div>
            <input type="submit" value="login" />
            <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        </form>

Geben Sie die Seite nach der Anmeldung an

Standardmäßig wird das Übergangsziel nach der Anmeldung wie folgt gesteuert.

  1. Wenn Sie vor dem Anmelden auf eine URL zugegriffen haben, leiten Sie diese weiter
  2. Wenn Sie die Anmeldeseite direkt öffnen und sich anmelden, leiten Sie zum Anwendungsstamm (/) um (Standardziel).

Implementierung

hello.html


<!doctype html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Hello</title>
    </head>
    <body>
        <h1>Hello!!</h1>
    </body>
</html>

Fügen Sie einen einfachen Bildschirm hinzu.

Funktionsprüfung

spring-security.jpg

Greifen Sie auf / hello.html zu.

spring-security.jpg

Sie werden zum Anmeldebildschirm weitergeleitet, melden Sie sich also an.

spring-security.jpg

Sie werden zu der Seite (/ hello.html) weitergeleitet, auf die Sie vor dem Anmelden zugegriffen haben.

Melden Sie sich dann einmal ab und greifen Sie direkt auf die Anmeldeseite (/ login) zu.

spring-security.jpg

Anmeldung.

spring-security.jpg

Es wird zum Anwendungsstamm (/) übersprungen.

Ändern Sie das Standardziel

Sie können das Übergangsziel ändern, nachdem Sie die Anmeldeseite direkt geöffnet und sich mit der Standardziel-URL angemeldet haben

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"
       ...>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login default-target-url="/hello.html" />
        <sec:logout />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().defaultSuccessUrl("/hello.html");
    }

    ...
}

Funktionsprüfung

Greifen Sie direkt auf den Anmeldebildschirm (/ login) zu.

spring-security.jpg

Anmeldung

spring-security.jpg

Sie werden zu der URL (/ hello.html) übersprungen, die durch default-target-url angegeben wird.

Wechseln Sie immer zum Standardziel

Auch wenn es eine Seite gibt, auf die Sie vor dem Anmelden zugreifen wollten, ändern Sie sie so, dass sie nach dem Anmelden zum Standardziel übergeht.

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"
       ...>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login default-target-url="/hello.html"
                        always-use-default-target="true" />
        <sec:logout />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig


...

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().defaultSuccessUrl("/hello.html", true);
    }

    ...
}

Funktionsprüfung

spring-security.jpg

Greifen Sie auf die entsprechende URL zu.

spring-security.jpg

Sie werden zum Anmeldebildschirm weitergeleitet, melden Sie sich also an.

spring-security.jpg

Sie werden zu der durch "default-target-url" angegebenen Seite übersprungen.

Implementieren Sie den Prozess, wenn die Anmeldung erfolgreich ist

Implementierung

MyAuthenticationSuccessHandler.java


package sample.spring.security.handler;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    
    @Override
    public void onAuthenticationSuccess(
            HttpServletRequest request, HttpServletResponse response, Authentication authentication)
                throws IOException, ServletException {
        RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        redirectStrategy.sendRedirect(request, response, "/hello.html");
    }
}

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="authenticationSuccessHandler"
          class="sample.spring.security.handler.MyAuthenticationSuccessHandler" />
    
    <sec:http>
        ...
        <sec:form-login authentication-success-handler-ref="authenticationSuccessHandler" />
        ...
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

import sample.spring.security.handler.MyAuthenticationSuccessHandler;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                .and()
                .formLogin().successHandler(new MyAuthenticationSuccessHandler());
    }

    ...
}

Der Betriebszustand wird weggelassen, da er nur zu / hello.html umleitet.

Wenn gleichzeitig mit dem Standardziel angegeben

Wenn Sie gleichzeitig das Standardziel und "AuthenticationSuccessHandler" angeben, funktioniert dies wie folgt.

Der Namespace wird priorisiert, um die Einstellungen zu bestimmen, aber die Java-Konfiguration überschreibt die Einstellungen, wenn die Methode aufgerufen wird, sodass dieser Unterschied gemacht wird.

Implementieren Sie den Prozess, wenn die Anmeldung fehlschlägt

MyAuthenticationFailureHandler.java


package sample.spring.security.handler;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    
    @Override
    public void onAuthenticationFailure(
            HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
                throws IOException, ServletException {
        DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        redirectStrategy.sendRedirect(request, response, "/login");
    }
}

--Erstellen Sie eine Klasse, die AuthenticationFailureHandler implementiert

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="authenticationFailureHandler"
          class="sample.spring.security.handler.MyAuthenticationFailureHandler" />
    
    <sec:http>
        ...
        <sec:form-login authentication-failure-handler-ref="authenticationFailureHandler"/>
        ...
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

import sample.spring.security.handler.MyAuthenticationFailureHandler;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                    .failureHandler(new MyAuthenticationFailureHandler());
    }

    ...
}

Der Vorgang wird weggelassen, da er einfach zum Anmeldebildschirm zurückkehrt.

Identifizieren Sie die Ursache für den Anmeldefehler

Das "onAuthenticationFailure ()" des "AuthenticationFailureHandler" kann die Ausnahme empfangen, die während der Authentifizierung am Ende des Arguments aufgetreten ist. Durch Untersuchen dieser Ausnahme kann die Ursache des Anmeldefehlers identifiziert werden.

Wenn Sie die Fehlermeldung anpassen möchten, wenn das Konto gesperrt ist, können Sie sie meiner Meinung nach hier steuern.

Ausnahme Lage
BadCredentialsException Der Benutzer existiert nicht, das Passwort ist falsch usw.
LockedException UserDetails.isAccountNonLocked()AberfalseIst zurückgekommen
DisabledException UserDetails.isEnabled()AberfalseIst zurückgekommen
AccountExpiredException UserDetails.isAccountNonExpired()AberfalseIst zurückgekommen
CredentialsExpiredException UserDetails.isCredentialsNonExpired()AberfalseIst zurückgekommen
SessionAuthenticationException Wenn die Anzahl der Sitzungen die Obergrenze überschreitet (Details zu einem späteren Zeitpunkt

Genehmigung

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"
       ...>

    ...

    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated() and hasAuthority('USER')" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="hoge"
                    password="hoge"
                    authorities="USER" />
                <sec:user
                    name="fuga"
                    password="fuga"
                    authorities="" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
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
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().access("isAuthenticated() and hasAuthority('USER')")
                .and()
                .formLogin();
    }
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("hoge")
            .password("hoge")
            .authorities("USER")
            .and()
            .withUser("fuga")
            .password("fuga")
            .authorities(Collections.emptyList());
    }
}

Funktionsprüfung

spring-security.jpg

Melden Sie sich als Hoge-Benutzer an

spring-security.jpg

Die obere Seite kann angezeigt werden.

spring-security.jpg

Dann melden Sie sich als Fuga-Benutzer an

spring-security.jpg

403 Ich erhalte eine Fehlermeldung.

Erläuterung

applicationContext.xml


    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated() and hasAuthority('USER')" />
        <sec:form-login />
        <sec:logout />
    </sec:http>

applicationContext.xml


    <sec:user
        name="hoge"
        password="hoge"
        authorities="USER" />
    <sec:user
        name="fuga"
        password="fuga"
        authorities="" />

Wie es funktioniert

Zeitpunkt der Ausführung des Autorisierungsprozesses

認可処理のタイミング.png

Der URL-basierte Autorisierungsprozess wird am Ende der Reihe von "Filter" -Prozessen durchgeführt. Dies wird von "AccessDecisionManager" im Prozess von "FilterSecurityInterceptor" durchgeführt.

Urteil durch Abstimmung

Die standardmäßig von Spring Security bereitgestellte Implementierung von "AccessDecisionManager" bestimmt, ob der Zugriff durch ** "Abstimmung" ** möglich ist oder nicht.

Die Implementierungsklasse von "AccessDecisionManager" kann mehrere Abstimmungsklassen mit dem Namen "AccessDecisionVoter" haben. Anschließend wird mit jedem "AccessDecisionVoter" geprüft (abgestimmt), ob der aktuelle Benutzer Zugriffsberechtigung für das Ziel (sicheres Objekt) hat oder nicht. Das Abstimmungsergebnis lautet entweder "Gewähren (" ACCESS_GRANTED ")", "Ablehnen (" ACCESS_DENIED ")" oder "Zurückziehen (" ACCESS_ABSTAIN ")". Die Implementierungsklasse von "AccessDecisionManager" aggregiert die Abstimmungsergebnisse von "AccessDecisionVoter" und entscheidet über den endgültigen Zugriff.

認可処理の流れ.png

Abhängig von der Aggregationsmethode gibt es drei Implementierungsklassen von "AccessDecisionManager", "AffirmativeBased", "ConsensusBased" und "UnanimousBased".

Der Standardwert ist "AffirmativeBased".

So bestimmen Sie Zugriffsrechte

Die drei Standardimplementierungsklassen von "AccessDecisionManager" bestimmen nicht direkt das Vorhandensein oder Fehlen von Zugriffsrechten. Es ist die Wählerklasse, die die Schnittstelle "AccessDecisionVoter" implementiert, die tatsächlich das Vorhandensein oder Fehlen von Zugriffsrechten bestimmt.

Die AccessDecisionVoter -Schnittstelle hat die folgende Definition (nur einige).

AccessDecisionVoter


package org.springframework.security.access;

import java.util.Collection;

import org.springframework.security.core.Authentication;

public interface AccessDecisionVoter<S> {
	int ACCESS_GRANTED = 1;
	int ACCESS_ABSTAIN = 0;
	int ACCESS_DENIED = -1;

	...

	int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);

}

Es gibt eine Methode, um "vote ()" abzustimmen. Diese Methode bestimmt das Vorhandensein eines Zugriffsrechts anhand der Informationen des empfangenen Arguments und gibt eine der Konstanten ("ACCESS_GRANTED", "ACCESS_ABSTAIN", "ACCESS_DENIED") zurück, die auch in "AccessDecisionVoter" definiert sind.

Jedes Argument hat die folgende Bedeutung.

Die Implementierungsklasse von "AccessDecisionVoter" erhält die dem Benutzer gewährten Berechtigungen aus "Authentifizierung". Dann wird beurteilt, ob der Benutzer Zugriffsberechtigung hat oder nicht, indem er mit der Sicherheitseinstellung verglichen wird, die in "Attributen" übergeben wird.

Implementierung von AccessDecisionVoter

Wenn "true" im Attribut "use-expression" des Tags "" angegeben ist (Standard ist "true"), wird "WebExpressionVoter" zum Implementieren von "AccessDecisionVoter" verwendet.

Diese Klasse ist ein Ausdruck, ein Wähler, der einen Ausdruck (SpEL) auswertet, um den Zugriff zu bestimmen.

Zusätzlich zu "AccessDecisionVoter" gibt es "RoleVoter" und "PreInvocationAuthorizationAdviceVoter", die für die Methodensicherheit verwendet werden.

Erteilte Berechtigung, die die Berechtigung des Benutzers darstellt

Eine Methode namens "getAuthorities ()" ist in der "Authentication" -Schnittstelle definiert. Diese Methode gibt eine Sammlung von "GrantedAuthority" zurück.

GrantedAuthority ist auch eine Schnittstelle, da der Name " dem Benutzer erteilte Berechtigungen " impliziert. Für "GrantedAuthority" ist nur eine Methode definiert, die "String" mit dem Namen "getAuthority ()" zurückgibt. Diese Methode soll "eine Zeichenfolgendarstellung der Berechtigungen zurückgeben, die durch eine Instanz von" GrantedAuthority "dargestellt werden" [^ 2]. Kurz gesagt, es handelt sich um eine Zeichenfolge, die eine solche Berechtigung darstellt, z. B. "ROLE_USER" oder "OP_REGISTER_ITEM".

[^ 2]: Wenn die Berechtigung nicht durch eine einfache Zeichenfolge ausgedrückt werden kann, wird standardmäßig "null" zurückgegeben. Die Standardimplementierung (z. B. "SimpleGrantedAuthority") gibt jedoch grundsätzlich eine Zeichenfolge zurück, sodass die Erläuterung dieses Falls hier weggelassen wird.

In Hello World lautet der im Attribut "Behörden" des Tags "" festgelegte Wert "GrantedAuthority".

applicationContext.xml


<sec:user
    name="hoge"
    password="hoge"
    authorities="USER" />★ Dies

Die hier festgelegten Berechtigungsinformationen werden anfänglich in der Klasse gespeichert, die "UserDetetails" implementiert. Wenn der Authentifizierungsprozess dann von "AuthenticationProvider" ausgeführt wird, wird er von der "getAuthorities ()" -Methode von "UserDetails" erfasst und in der "Authentication" -Instanz gespeichert.

Zusammenfassung des Mechanismus

認可仕組みまとめ.png

--FilterSecurityInterceptor weist AccessDecisionManager (AffirmativeBased) an, das Zugriffsrecht zu bestimmen. --AffirmativeBased delegiert die Bestimmung der Zugriffsrechte an AccessDecisionVoter (WebExpressionVoter). --WebExpressionVoter erhält eine Sammlung von GrantedAuthority von Authentication. --WebExpressionVoter führt den bedingten Ausdruck (SpEL) aus den Argumentinformationen und den Informationen zu GrantedAuthority aus. --Wenn das Bewertungsergebnis des Ausdrucks "wahr" ist, wird die Autorisierung zurückgegeben, und wenn es "falsch" ist, wird die Ablehnung als Abstimmungsergebnis zurückgegeben. --AffirmativeBased aggregiert die Abstimmungsergebnisse der Wähler und bestimmt, ob Sie Zugriffsrechte haben oder nicht.

Ausdrucksbasierte Zugriffskontrolle

Wenn "WebExpressionVoter" zum Implementieren von "AccessDecisionVoter" verwendet wird, kann die ausdrucksbasierte Zugriffssteuerung im Attribut "access" des Tags "" definiert werden.

Für die hier verwendeten Ausdrücke wird Spring Expression Language (SpEL) verwendet. Spring Security wurde erweitert, damit Sie Ihre eigenen Funktionen und Variablen verwenden können, um die Definition von Zugriffskontrollen zu vereinfachen.

Schreiben Sie diesen Ausdruck so, dass er letztendlich zu einem einzelnen "Booleschen Wert" ausgewertet wird. Wenn dann das Bewertungsergebnis des Ausdrucks "wahr" ist, ist der Zugriff zulässig, und wenn es "falsch" ist, wird der Zugriff verweigert.

Verfügbare Funktionen / Variablen </ span>

Funktionen / Variablen Überprüfen Sie den Inhalt / die Werte Beispiel
hasRole(String) Hat die angegebene Rolle hasRole('USER')
hasAnyRole(String...) Hat eine der angegebenen Rollen hasAnyRole('FOO', 'ROLE_BAR')
hasAuthority(String) Haben Sie die angegebene Berechtigung hasAuthority('CREATE_TICKET')
hasAnyAuthority(String...) Haben Sie eine der angegebenen Berechtigungen hasAnyAuthority('CREATE_TICKET', 'MANAGE_TICKET')
isAnonymous() Anonym authentifiziert sein -
isRememberMe() Remember-Ich zertifiziert -
isAuthenticated() Muss zertifiziert sein -
isFullyAuthenticated() Seien Sie vollständig authentifiziert -
permitAll immertrueWird bewertet als -
denyAll immerfalseWird bewertet als -

Die Beziehung zwischen "isAnonymous ()", "isRememberMe ()", "isAuthenticated ()" und "isFullyAuthenticated ()" ist wie folgt.

Anonyme Authentifizierung Remember-Ich Zertifizierung Vollständige Zertifizierung[^3]
isAnonymous() true false false
isRememberMe() false true false
isAuthenticated() false true true
isFullyAuthenticated() false false true

[^ 3]: Anmeldeinformationen (Passwort usw.) wurden erfolgreich geprüft und es wird garantiert, dass sie authentifiziert werden (kurz nach dem normalen Anmelden bei Form).

Unterschied zwischen "hasRole ()" und "hasAuthority ()"

Zu den Funktionen, die mit "WebExpressionVoter" verwendet werden können, gehören "hasRole ()" und "hasAuthority ()" als Funktionen zum Überprüfen der Berechtigung. Beide ändern nicht den Punkt, an dem überprüft wird, ob dem Benutzer "GrantedAuthority" vorhanden ist.

Der Unterschied besteht darin, dass hasRole () das Präfix ROLE_ vervollständigt.

Benutzerrechte → USER ROLE_USER
hasRole('USER') false true
hasRole('ROLE_USER') false true
hasAuthority('USER') true false
hasAuthority('ROLE_USER') false true

hasAuthority () überprüft, ob die Zeichenfolgendarstellung von GrantedAuthority genau übereinstimmt.

Andererseits ergänzt "hasRole ()" ROLE_ "und vergleicht es mit" GrantedAuthority ", wenn die als Argument übergebene Zeichenfolge nicht mit" ROLE_ "beginnt. (HasRole ('USER') ergänzt ROLE_ und vergleicht als ROLE_USER)

Was ist ROLLE?

Was ist der Unterschied zwischen Rolle und Autorität? Nichts ändert sich. Der einzige Unterschied besteht darin, ob es mit "ROLE_" beginnt oder nicht. Beide sind tatsächlich "GrantedAuthority".

Der Grund, warum der mit dem Präfix "ROLE_" speziell behandelt wird, ist, dass ** dies meine Vermutung ist **, aber es liegt an der Tatsache, dass "Voter" namens "RoleVoter" in der Vergangenheit verwendet wurde. Ich fühle.

WebExpressionVoter wurde in Version 3.0 hinzugefügt, und es scheint, dass die Kombination von ** Vielleicht ** RoleVoter und AuthenticatedVoter zuvor verwendet wurde.

Wenn Sie einen Namespace verwenden, können Sie dies tun, indem Sie use-expression in <http> auf false setzen.

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"
       ...>
    
    <sec:http use-expressions="false">
        <sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <sec:intercept-url pattern="/**" access="ROLE_ADMIN" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="user"
                    password="user"
                    authorities="ROLE_USER" />
                <sec:user
                    name="admin"
                    password="admin"
                    authorities="ROLE_ADMIN" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

SpEL kann nicht für den Zugriff auf verwendet werden. Schreiben Sie stattdessen die Einstellungen für "AuthenticatedVoter" und "RoleVoter".

IS_AUTHENTICATED_ANONYMOUSLY ist eine Einstellung für AuthenticatedVoter, um die anonyme Authentifizierung zu überprüfen (das heißt, es ist in Ordnung, auch wenn Sie sich nicht angemeldet haben).

Außerdem überprüft "ROLE_ADMIN", ob die Einstellung für "RoleVoter" die Berechtigung "ROLE_ADMIN" hat.

Da pattern =" / login " nur die Einstellung für AuthenticatedVoter hat, ist eine Überprüfung durch RoleVoter nicht erforderlich. Da "AccessDecisionManager" jedoch nicht beurteilen kann, ob dies erforderlich ist oder nicht [^ 4], soll jeder "AccessDecisionVoter" vorerst zur Abstimmung aufgefordert werden (hier sind "AuthenticatedVoter" und "RoleVoter") Abstimmung).

[^ 4]: AccessDecisionManager weiß nicht (weiß nicht), ob die eigentliche Klasse hinter der AccessDecisionVoter-Schnittstelle RoleVoter ist.

Ob dies erforderlich ist oder nicht, wird durch die Methode "unterstützt (ConfigAttribute)" jedes Wählers bestimmt. Das Folgende ist die support () Methode von RoleVoter.

RoleVoter unterstützt()Methode


    public boolean supports(ConfigAttribute attribute) {
        if ((attribute.getAttribute() != null)
                && attribute.getAttribute().startsWith(getRolePrefix())) {
            return true;
        }
        else {
            return false;
        }
    }

Für attribute wird der durch das Attribut access angegebene Wert übergeben (wenn mehrere durch Kommas getrennt angegeben werden, werden sie einzeln übergeben). getRolePrefix () gibt "ROLE_" zurück.

Mit anderen Worten, es wird überprüft, ob der durch das Attribut "access" angegebene Wert mit "ROLE_" beginnt, und wenn es gestartet wird, wird es unterstützt, andernfalls wird es nicht unterstützt. Wenn dies nicht unterstützt wird, gibt "RoleVoter" als Ergebnis der Abstimmung einen "Rückzug" zurück.

Auf diese Weise führt RoleVoter keine unnötige Verarbeitung der Berechtigungsprüfung durch, indem der Berechtigungsname mit ROLE_ beginnt. In ähnlicher Weise wird "AuthenticatedVoter" nur verarbeitet, wenn der durch "access" angegebene Wert eine bestimmte Zeichenfolge ist. Mit anderen Worten, Einstellungswerte, die mit "ROLE_" beginnen, werden nicht unterstützt und nicht verarbeitet.

Auf diese Weise kontrolliert jeder "Wähler" das Vorhandensein oder Fehlen von Unterstützung, so dass kein unnötiges Urteil gefällt wird. Das Ergebnis ist ein spezielles Präfix namens "ROLE_".

Mit dem Erscheinen von "WebExpressionVoter" ist es jedoch möglich geworden, flexibel mit SpEL zu definieren, und ich bin der Meinung, dass die Notwendigkeit, mehrere "Wähler" zu kombinieren, abgenommen hat. (Selbst wenn Sie versuchen, "WebExpressionVoter" und "RoleVoter" zu kombinieren, tritt beim Parsen von "access =" ROLE_USER "ein Fehler beim Parsen des SpEL-Ausdrucks auf, und Sie können ihn überhaupt nicht kombinieren.)

Beziehen Sie sich auf die Bean aus dem SpEL-Ausdruck

Implementierung

MyExpression.java


package sample.spring.security.expression;

import org.springframework.security.core.Authentication;

public class MyExpression {

    public boolean check(Authentication authentication) {
        String name = authentication.getName();
        System.out.println("name = " + name);
        return "hoge".equals(name);
    }
}

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="myExpression" class="sample.spring.security.expression.MyExpression" />
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="@myExpression.check(authentication)" />
        <sec:form-login />
        <sec:logout />
    </sec:http>

    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                        name="hoge"
                        password="hoge"
                        authorities="" />
                <sec:user
                        name="fuga"
                        password="fuga"
                        authorities="" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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 sample.spring.security.expression.MyExpression;

import java.util.Collections;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().access("@myExpression.check(authentication)")
                .and()
                .formLogin();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("hoge")
                .password("hoge")
                .authorities(Collections.emptyList())
                .and()
                .withUser("fuga")
                .password("fuga")
                .authorities(Collections.emptyList());
    }
    
    @Bean
    public MyExpression myExpression() {
        return new MyExpression();
    }
}

Funktionsprüfung

Beim Zugriff mit "hoge" links, beim Zugriff mit "fuga" rechts

spring-security.jpg

Serverprotokoll


name = hoge
name = fuga

Erläuterung

MyExpression.java


package sample.spring.security.expression;

import org.springframework.security.core.Authentication;

public class MyExpression {

    public boolean check(Authentication authentication) {
        String name = authentication.getName();
        System.out.println("name = " + name);
        return "hoge".equals(name);
    }
}

applicationContext.xml


    <sec:http>
        ...
        <sec:intercept-url pattern="/**" access="@myExpression.check(authentication)" />
        ...
    </sec:http>

Objekte, für die Konstanten und Funktionen definiert sind

Für allowAll und hasAuthority () SecurityExpressionRoot Es ist in expression / SecurityExpressionRoot.html definiert.

Wenn die Zugriffssteuerung auf "Filter" verarbeitet wird, wird WebSecurityExpressionRoot verwendet. web / access / expression / WebSecurityExpressionRoot.html) wird verwendet.

Verwenden Sie Ihren eigenen Wähler

Implementierung

AcceptFugaVoter.java


package sample.spring.security.voter;

import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

public class AcceptFugaVoter implements AccessDecisionVoter<Object> {
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
        Object principal = authentication.getPrincipal();
        if (!(principal instanceof UserDetails)) {
            return ACCESS_ABSTAIN;
        }

        String username = ((UserDetails)principal).getUsername();
        return "fuga".equals(username) ? ACCESS_GRANTED : ACCESS_DENIED;
    }
}

Ein schlampiger Wähler, der den Zugriff ermöglicht, wenn der Benutzername "fuga" lautet.

namespace

application.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="accessDecisionManager"
          class="org.springframework.security.access.vote.AffirmativeBased">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter" />
                <bean class="sample.spring.security.voter.AcceptFugaVoter" />
            </list>
        </constructor-arg>
    </bean>
    
    <sec:http access-decision-manager-ref="accessDecisionManager">
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="hasAuthority('HOGE')" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="hoge"
                    password="hoge"
                    authorities="HOGE" />
                <sec:user
                    name="fuga"
                    password="fuga"
                    authorities="" />
                <sec:user
                    name="piyo"
                    password="piyo"
                    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.security.access.AccessDecisionManager;
import org.springframework.security.access.vote.AffirmativeBased;
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.access.expression.WebExpressionVoter;
import sample.spring.security.voter.AcceptFugaVoter;

import java.util.Arrays;
import java.util.Collections;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .accessDecisionManager(this.createAccessDecisionManager())
                .antMatchers("/login").permitAll()
                .anyRequest().hasAuthority("HOGE")
                .and()
                .formLogin();
    }
    
    private AccessDecisionManager createAccessDecisionManager() {
        return new AffirmativeBased(Arrays.asList(
            new WebExpressionVoter(),
            new AcceptFugaVoter()
        ));
    }
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("hoge")
            .password("hoge")
            .authorities("HOGE")
        .and()
            .withUser("fuga")
            .password("fuga")
            .authorities(Collections.emptyList())
        .and()
            .withUser("piyo")
            .password("piyo")
            .authorities(Collections.emptyList());
    }
}

Funktionsprüfung

Von links nach rechts der Status nach dem Anmelden als Benutzer "hoge", "fuga", "piyo".

spring-security.jpg

Erläuterung

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="accessDecisionManager"
          class="org.springframework.security.access.vote.AffirmativeBased">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.web.access.expression.WebExpressionVoter" />
                <bean class="sample.spring.security.voter.AcceptFugaVoter" />
            </list>
        </constructor-arg>
    </bean>
    
    <sec:http access-decision-manager-ref="accessDecisionManager">
        ...
    </sec:http>
    
    ...
</beans>

Rollenvererbung

Die Rolle hat eine Vererbungsbeziehung

Die Rolle hat normalerweise eine Vererbungsbeziehung.

Wenn beispielsweise Rollen für "Benutzer" und "Administrator" vorhanden sind, erbt "Administrator" normalerweise "Benutzer". Mit anderen Worten, was ein "Benutzer" tun kann, kann auch von einem "Administrator" getan werden.

Wenn Sie jedoch versuchen, dies einfach mit oder ohne Rolle zu steuern, lauten die Einstellungen wie folgt.

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"
       ...>
    
    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/hierarchy/admin" access="hasRole('ADMIN')" />
        <sec:intercept-url pattern="/hierarchy/user" access="hasRole('USER') or hasRole('ADMIN')" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="user"
                    password="user"
                    authorities="ROLE_USER" />
                <sec:user
                    name="admin"
                    password="admin"
                    authorities="ROLE_ADMIN" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

/ hierarchy / admin ist nur für den" Administrator "zugänglich, und / hierarchy / user ist für den" Benutzer "zugänglich.

Für / hierarchy / admin einfach hasRole ('ADMIN'). / Hierarchie / Benutzer ist jedoch hasRole ('USER') oder hasRole ('ADMIN'). Wenn nur "hasRole (" USER ")" verwendet wird, wird es blockiert, wenn ein Benutzer mit nur "ROLE_ADMIN" darauf zugreift. Dies ist also eine redundante Einstellung.

Wenn Sie auf diese Weise versuchen, die Vererbungsbeziehung der Rolle einfach mit oder ohne Rolle zu realisieren, legen Sie die untergeordnete Rolle (ROLE_ADMIN) an allen Stellen fest, an denen die übergeordnete Rolle ( ROLE_USER) angegeben ist. Du wirst müssen.

Es gibt auch eine Möglichkeit, nur "hasRole" ("USER") für "access" festzulegen und "USER" immer zusammen mit "ADMIN" für "Authority" festzulegen. In jedem Fall besteht jedoch kein Unterschied darin, dass die Beschreibung redundant ist.

Definieren Sie die Rollenvererbung mithilfe von RoleHierarchy

Spring Security bietet einen Mechanismus zum Definieren von Rollenvererbungsbeziehungen.

Die vorherige Einstellung kann mithilfe von "RoleHierarchy" wie folgt umgeschrieben werden.

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"
       ...>

    <bean id="roleHierarchy"
          class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_ADMIN > ROLE_USER
            </value>
        </property>
    </bean>
    
    <bean id="expressionHandler"
          class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="roleHierarchy" ref="roleHierarchy" />
    </bean>
    
    <sec:http>
        <sec:expression-handler ref="expressionHandler" />
        
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/hierarchy/admin" access="hasRole('ADMIN')" />
        <sec:intercept-url pattern="/hierarchy/user" access="hasRole('USER')" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="user"
                    password="user"
                    authorities="ROLE_USER" />
                <sec:user
                    name="admin"
                    password="admin"
                    authorities="ROLE_ADMIN" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Java Configuration

MySpringSecurityConfig.java


package sample.spring.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.expression.SecurityExpressionHandler;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
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.FilterInvocation;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .expressionHandler(this.createSecurityExpressionHandler())
                .antMatchers("/login").permitAll()
                .antMatchers("/hierarchy/user").hasRole("USER")
                .antMatchers("/hierarchy/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
    
    private SecurityExpressionHandler<FilterInvocation> createSecurityExpressionHandler() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");

        DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy);
        
        return expressionHandler;
    }
    
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user")
            .password("user")
            .roles("USER")
        .and()
            .withUser("admin")
            .password("admin")
            .roles("ADMIN");
    }
}

Funktionsprüfung

Melden Sie sich als "Benutzer" bzw. "Administrator" an, um auf "/ hierarchy / user" und "/ hierarchy / admin" zuzugreifen.

** Wenn als Benutzer angemeldet **

spring-security.jpg

** Wenn Sie sich als Administrator anmelden **

spring-security.jpg

Erläuterung

Definition von RoleHierarchyImpl


    <bean id="roleHierarchy"
          class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_ADMIN > ROLE_USER
            </value>
        </property>
    </bean>

--Lean RoleHierarchyImpl als Implementierungsklasse für die RoleHierarchy -Schnittstelle.

Wenn Sie mehr als eine definieren

ROLE_A > ROLE_B
ROLE_B > ROLE_C

Sie können dies so tun (Zeilenumbrüche sind nicht erforderlich, aber leichter zu erkennen).

Legen Sie RoleHierarchyImpl fest, das für die Ausdrucksauswertung verwendet werden soll


    <bean id="roleHierarchy"
          class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        ...
    </bean>
    
    <bean id="expressionHandler"
          class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="roleHierarchy" ref="roleHierarchy" />
    </bean>
    
    <sec:http>
        <sec:expression-handler ref="expressionHandler" />
        
        ...
    </sec:http>

Stellen Sie dann dieses "RoleHierarchyImpl" ein, das bei der Auswertung des SpEL verwendet werden soll.

Registrieren Sie dazu "SecurityExpressionHandler" als Bean. Verwenden Sie "DefaultWebSecurityExpressionHandler" als Implementierungsklasse und geben Sie die "RoleHierarchyImpl" an, die zuvor in der Eigenschaft "roleHierarchy" definiert wurde.

Fügen Sie dann "" als Unterelement von "" hinzu und geben Sie "SecurityExpressionHandler" im Attribut "ref" an.

Verwenden Sie WebExpressionVoter nicht

Verwenden Sie "RoleHierarchyVoter" ohne "WebExpressionVoter".

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"
       ...>

    <bean id="roleHierarchy"
          class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_ADMIN > ROLE_USER
            </value>
        </property>
    </bean>
    
    <bean id="roleHierarchyVoter"
          class="org.springframework.security.access.vote.RoleHierarchyVoter">
        <constructor-arg ref="roleHierarchy" />
    </bean>
    
    <bean id="accessDecisionManager"
          class="org.springframework.security.access.vote.AffirmativeBased">
        <constructor-arg>
            <list>
                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
                <ref bean="roleHierarchyVoter" />
            </list>
        </constructor-arg>
    </bean>
    
    <sec:http use-expressions="false"
              access-decision-manager-ref="accessDecisionManager">
        <sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
        <sec:intercept-url pattern="/hierarchy/admin" access="ROLE_ADMIN" />
        <sec:intercept-url pattern="/hierarchy/user" access="ROLE_USER" />
        <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
        <sec:form-login />
        <sec:logout />
    </sec:http>
    
    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user
                    name="user"
                    password="user"
                    authorities="ROLE_USER" />
                <sec:user
                    name="admin"
                    password="admin"
                    authorities="ROLE_ADMIN" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

Kontrolle zum Zeitpunkt des Autorisierungsfehlers

Geben Sie die Fehlerseite an

Implementierung

access-denied.html


<!doctype html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Autorisierungsfehler</title>
    </head>
    <body>
        <h1>Die Operation ist nicht erlaubt!</h1>
    </body>
</html>

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="/test" access="hasAuthority('HOGE')" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:access-denied-handler error-page="/access-denied.html" />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                .and()
                .exceptionHandling().accessDeniedPage("/access-denied.html");
    }

    ...
}

Funktionsprüfung

Nachdem Sie sich mit "hoge" angemeldet haben, greifen Sie auf "/ test" zu

spring-security.jpg

Erläuterung

applicationContext.xml


<sec:access-denied-handler error-page="/access-denied.html" />

MySpringSecurityConfig.java


.exceptionHandling().accessDeniedPage("/access-denied.html");

Kontrolle mit beliebiger Implementierung

Implementierung

MyAccessDeniedHandler.java


package sample.spring.security.handler;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyAccessDeniedHandler implements AccessDeniedHandler {
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        if (response.isCommitted()) {
            return;
        }
        
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);

        DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        redirectStrategy.sendRedirect(request, response, "/access-denied.html");
    }
}

--Erstellen Sie eine Klasse, die "AccessDeniedHandler" implementiert, und implementieren Sie die Verarbeitung zum Zeitpunkt des Autorisierungsfehlers in der Methode "handle ()".

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="accessDeniedHandler"
          class="sample.spring.security.handler.MyAccessDeniedHandler" />
    
    <sec:http>
        ...
        <sec:access-denied-handler ref="accessDeniedHandler" />
    </sec:http>

    ...
</beans>

Java Configuration

MySpringSecurityConfig.java


...

import sample.spring.security.handler.MyAccessDeniedHandler;

@EnableWebSecurity
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                ...
                .and()
                .exceptionHandling().accessDeniedHandler(new MyAccessDeniedHandler());
    }

    ...
}

Ausführungsergebnis

Arbeiten Sie genauso wie bei Angabe von "Fehlerseite".

spring-security.jpg

Jetzt können Sie sehen, dass sich die URL geändert hat und jetzt eine Weiterleitung ist.

Referenz

Recommended Posts

Spring Security-Nutzungsnotiz Authentifizierung / Autorisierung
Spring Security-Nutzungsnotiz CSRF
Spring Security-Nutzungsnotiz Run-As
Sicherheit der Verwendungsnotizmethode für Spring Security
Spring Security-Nutzungsnotiz Remember-Me
Spring Security-Nutzungsnotiz CORS
Spring Security-Verwendungsnotiztest
Antwortheader für die Verwendung von Spring Security
Sitzungsverwaltung für Spring Security-Nutzungsnotizen
Spring Security-Nutzungsnotiz Basic / Mechanismus
Zertifizierung / Autorisierung mit Spring Security & Thymeleaf
Spring Security Usage Memo Domänenobjektsicherheit (ACL)
Informationen zur Spring Security-Authentifizierung
Hinweise zur Verwendung von Spring Shell
Verwendungshinweis zu Spring Security: Zusammenarbeit mit Spring MVC und Boot
Implementierte Authentifizierungsfunktion mit Spring Security ②
Implementierte Authentifizierungsfunktion mit Spring Security ③
Spring Boot Tutorial Verwenden der Spring Security-Authentifizierung
Implementierte Authentifizierungsfunktion mit Spring Security ①
Erfahren Sie mehr über die Architektur der Spring Security-Authentifizierungsverarbeitung
Setzen Sie das Spring Security-Authentifizierungsergebnis auf JSON
DB-Authentifizierung mit Spring Security und Hashing mit BCrypt
Erreichen Sie die BASIC-Authentifizierung mit Spring Boot + Spring Security
Frühlingsrückblick Memo
Verwendungshinweise zu JavaParser
Hinweise zur Verwendung von WatchService
PlantUML-Nutzungsnotiz
Verwendungshinweise zu JUnit5
Versuchen Sie die LDAP-Authentifizierung mit Spring Security (Spring Boot) + OpenLDAP
Fügen Sie mit Spring Security Ihre eigenen Authentifizierungselemente hinzu
[Einführung in Spring Boot] Authentifizierungsfunktion mit Spring Security
JJUG CCC Frühjahr 2018 Memo
Schreiben von Frühlingsstiefel-Memos (1)
Spring Security erhöht 403 verboten
Schreiben von Spring Boot-Memos (2)
Erstellen Sie eine API-Schlüsselauthentifizierung für die Web-API in Spring Security
Neuer Mitarbeiter hat versucht, mit Spring Security eine Authentifizierungs- / Autorisierungsfunktion von Grund auf neu zu erstellen
[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
Beim Testen der Formularauthentifizierung mit Spring Security tritt ein 404-Fehler auf