[JAVA] Sicherheit der Verwendungsnotizmethode für Spring Security

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

Sonderedition Was Spring Security kann und was nicht


Spring Security unterstützt die Zugriffssteuerung auf Methodenebene zusätzlich zur Zugriffssteuerung durch Angabe einer URL. Es wird empfohlen, die Zugriffssteuerung auf Methodenebene auf Serviceebene durchzuführen, ohne sich ausschließlich auf die URL-basierte Zugriffssteuerung zu verlassen.

http://docs.spring.io/spring-security/site/docs/4.2.1.RELEASE/reference/htmlsingle/#request-matching

In practice we recommend that you use method security at your service layer, to control access to your application, and do not rely entirely on the use of security constraints defined at the web-application level. [Übersetzung] In der Praxis empfehlen wir, dass Sie die Methodensicherheit auf der Serviceebene verwenden, um den Zugriff auf Ihre Anwendung zu steuern, und der Verwendung von Sicherheitsbeschränkungen, die auf Webanwendungsebene definiert sind, nicht vollständig vertrauen.

URLs change and it is difficult to take account of all the possible URLs that an application might support and how requests might be manipulated. [Übersetzung] Es ist schwierig zu überlegen, wie alle URLs und Anforderungen behandelt werden sollen, die Ihre Anwendung unterstützt, wenn sich die URL ändert.

Security defined at the service layer is much more robust and harder to bypass, so you should always take advantage of Spring Security’s method security options. [Übersetzung] Die auf der Serviceebene definierte Sicherheit ist robuster und schwer zu umgehen [^ 5]. Daher sollten Sie immer die Methodensicherheitsoptionen von Spring Security nutzen.

[^ 5]: Sicherheitsüberprüfungen umgehen

Überprüfen Sie dies, bevor Sie die Methode ausführen

Implementierung

MyMethodSecurityService.java


package sample.spring.security.service;

import org.springframework.security.access.prepost.PreAuthorize;

public class MyMethodSecurityService {
    
    @PreAuthorize("hasAuthority('ADMIN')")
    public String execute() {
        return "Hello Method Security!!";
    }
}

MyMethodSecurityServlet.java


package sample.spring.security.servlet;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import sample.spring.security.service.MyMethodSecurityService;

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("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {

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

        PrintWriter writer = resp.getWriter();
        try {
            writer.println(service.getMessage());
        } catch (AccessDeniedException e) {
            writer.println(e.getMessage());
        } finally {
            writer.close();
        }
    }
}

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:global-method-security pre-post-annotations="enabled" />

    <bean class="sample.spring.security.service.MyMethodSecurityService" />

    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <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="USER" />
                <sec:user name="admin" password="admin" authorities="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.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.service.MyMethodSecurityService;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin();
    }
    
    @Bean
    public MyMethodSecurityService myMethodSecurityService() {
        return new MyMethodSecurityService();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("user")
                .authorities("USER")
            .and()
                .withUser("admin")
                .password("admin")
                .authorities("ADMIN");
    }
}

Funktionsprüfung

Oben ist, wenn Sie sich als "Benutzer" anmelden, und unten, wenn Sie sich als "Administrator" anmelden.

spring-security.jpg

Erläuterung

applicationContext.xml


    <sec:global-method-security pre-post-annotations="enabled" />

MySpringSecurityConfig.java


@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MySpringSecurityConfig extends WebSecurityConfigurerAdapter {

--Um die Methodensicherheit zu aktivieren

MyMethodSecurityService.java


    @PreAuthorize("hasAuthority('ADMIN')")
    public String getMessage() {
        return "Hello Method Security!!";
    }

Führen Sie nach der Methode einen Überprüfungsprozess durch

Implementierung

MyMethodSecurityService.java


package sample.spring.security.service;

import org.springframework.security.access.prepost.PostAuthorize;

public class MyMethodSecurityService {
    
    @PostAuthorize("returnObject == 'hoge'")
    public String getMessage(String parameter) {
        System.out.println("parameter = " + parameter);
        return parameter;
    }
}

MyMethodSecurityServlet.java


package sample.spring.security.servlet;

...

@WebServlet("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {

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

        PrintWriter writer = resp.getWriter();
        try {
            String parameter = req.getParameter("parameter");
            writer.println(service.getMessage(parameter));
        } catch (AccessDeniedException e) {
            writer.println(e.getMessage());
        } finally {
            writer.close();
        }
    }
}

Die Einstellungen sind die gleichen wie bei [vorherige](# method-security-pre-authorize).

Funktionsprüfung

Zugriff auf / method-security? Parameter = hoge

Serverausgabe


parameter = hoge

spring-security.jpg

Zugriff auf / method-security? Parameter = fuga

Serverausgabe


parameter = fuga

spring-security.jpg

Erläuterung

MyMethodSecurityService.java


    @PostAuthorize("returnObject == 'hoge'")
    public String getMessage(String parameter) {
        System.out.println("parameter = " + parameter);
        return parameter;
    }

Referenzieren von Methodenargumenten in einem Ausdruck

Implementierung

MyMethodSecurityService.java


package sample.spring.security.service;

import org.springframework.security.access.prepost.PreAuthorize;

public class MyMethodSecurityService {

    @PreAuthorize("#strValue == 'aaa' and #intValue == 1")
    public String getMessage(String strValue, int intValue) {
        return "strValue=" + strValue + ", intValue=" + intValue;
    }
}

MyMethodSecurityServlet.java


package sample.spring.security.servlet;

...

@WebServlet("/method-security")
public class MyMethodSecurityServlet extends HttpServlet {

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

        PrintWriter writer = resp.getWriter();
        try {
            String strValue = req.getParameter("strValue");
            int intValue = Integer.parseInt(req.getParameter("intValue"));

            writer.println(service.getMessage(strValue, intValue));
        } catch (AccessDeniedException e) {
            writer.println(e.getMessage());
        } finally {
            writer.close();
        }
    }
}

Funktionsprüfung

Zugriff auf / method-security? StrValue = abc & intValue = 1

spring-security.jpg

Zugriff auf / method-security? StrValue = aaa & intValue = 1

spring-security.jpg

Erläuterung

MyMethodSecurityService.java


    @PreAuthorize("#strValue == 'aaa' and #intValue == 1")
    public String getMessage(String strValue, int intValue) {

So lösen Sie Methodenparameternamen auf

Der Parametername der Methode kann nicht durch Reflektion übernommen werden, wenn es sich um Java 7 oder weniger handelt. Wenn für Java 8 und höher zum Zeitpunkt der Kompilierung die Option "-parameters" angegeben wird, können Parameternamen durch Reflektion übernommen werden. /api/java/lang/reflect/Parameter.html).

Spring bietet Lösungen für verschiedene Parameternamen, um diese Situationen zu bewältigen.

Explizit kommentieren

python


package sample.spring.security.service;

import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PreAuthorize;

public class MyMethodSecurityService {
    
    @PreAuthorize("#strValue == 'aaa' and #intValue == 1")
    public String getMessage(@P("strValue") String strValue, @P("intValue") int intValue) {
        return "strValue=" + strValue + ", intValue=" + intValue;
    }
}

Eine Anmerkung mit dem Namen "@ P" wird bereitgestellt. Jetzt können Sie den Parameter mit Anmerkungen versehen und den Parameternamen mit "Wert" angeben, um den Parameternamen per Anmerkung zu erhalten.

Die Implementierungsklasse ist "AnnotationParameterNameDiscoverer".

Holen Sie sich durch Reflexion

Verfügbar für Java 8 und höher, wenn zur Kompilierungszeit mit der Option -parameters kompiliert wird.

Die Implementierungsklasse ist "StandardReflectionParameterNameDiscoverer".

Analysieren Sie die Klassendatei, um die Parameternamen abzurufen

Um diese Funktion verwenden zu können, müssen beim Kompilieren Debug-Informationen generiert werden. Insbesondere ist es notwendig, mindestens "vars" mit der Option "-g" anzugeben.

Wenn Sie mit Gradle kompilieren, ist diese Option übrigens standardmäßig aktiviert, sodass Sie diese Funktion verwenden können, ohne sich darüber Gedanken machen zu müssen.

Die Implementierungsklasse ist "LocalVariableTableParameterNameDiscoverer".


Die obigen Funktionen werden in der Reihenfolge "Annotation" -> "Reflection" -> "Class File Analysis" angewendet, und der zuerst gefundene Name wird verwendet.

Referenz

Recommended Posts

Sicherheit der Verwendungsnotizmethode für Spring Security
Spring Security-Nutzungsnotiz CSRF
Spring Security-Nutzungsnotiz Run-As
Spring Security-Nutzungsnotiz Remember-Me
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
Memo zur Spring Boot Controller-Methode
Verwendungshinweis zu Spring Security: Zusammenarbeit mit Spring MVC und Boot
Frühlingsrückblick Memo
Verwendungshinweise zu JavaParser
Hinweise zur Verwendung von WatchService
PlantUML-Nutzungsnotiz
Memo zur Installationsmethode von Spring Boot + Thymeleaf Boot Strap
Verwendungshinweise zu JUnit5
JJUG CCC Frühjahr 2018 Memo
Informationen zur Spring Security-Authentifizierung
Schreiben von Frühlingsstiefel-Memos (1)
Java-Lernnotiz (Methode)
Spring Security erhöht 403 verboten
Schreiben von Spring Boot-Memos (2)
Rufen Sie Ihre eigene Methode mit PreAuthorize in Spring Security auf
Spring Framework Selbststudium Memo series_1
Java Silver Lernmethode Memo
Erstellen Sie eine Java-Methode [Memo] [java11]
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
Entwurfsmuster nach Ruby Template-Methode Musternotiz
Implementierte Authentifizierungsfunktion mit Spring Security ②
◆ Konstruktionsnotiz für Spring Boot + Gradle-Umgebung
Spring Boot + PostgreSQL-Fehlerbehebungsmethode
Implementierte Authentifizierungsfunktion mit Spring Security ③
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-
[Java] Memo zur Verarbeitungszeitmessmethode
Verwendung von Thymeleaf mit Spring Boot
Spring 5 MVC-Webanwendungsentwicklung mit Visual Studio Code Spring Security-Nutzung 1/3 [Vorbereitung]