[JAVA] Spring Security Usage Memo Method Security

Histoire de base et systématique Histoire de certification / d'autorisation Histoire Remember-Me Histoire CSRF Histoire de gestion de session Parler de l'en-tête de réponse Histoire CORS L'histoire de Run-As L'histoire d'ACL Test story Parlez de la coopération avec MVC et Boot

Édition supplémentaire Ce que Spring Security peut et ne peut pas faire


Spring Security prend en charge le contrôle d'accès au niveau de la méthode en plus du contrôle d'accès en spécifiant une URL. Il est recommandé que le contrôle d'accès au niveau de la méthode soit effectué au niveau de la couche service, plutôt que de se fier uniquement au contrôle d'accès basé sur l'URL.

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. [Français] En pratique, nous vous recommandons d'utiliser la méthode de sécurité au niveau de la couche service pour contrôler l'accès à votre application et de ne pas faire totalement confiance à l'utilisation des contraintes de sécurité définies au niveau de l'application Web.

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. [Français] Il est difficile d'envisager comment gérer toutes les URL et demandes que votre application prend en charge lorsque l'URL change.

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. [Français] La sécurité définie au niveau de la couche service est plus robuste et difficile à contourner [^ 5]. Par conséquent, vous devez toujours profiter des options de sécurité des méthodes de Spring Security.

[^ 5]: contournement des contrôles de sécurité

Vérifiez avant d'exécuter la méthode

la mise en oeuvre

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");
    }
}

Contrôle de fonctionnement

Le haut est lorsque vous vous connectez en tant que ʻutilisateur, et le bas est lorsque vous vous connectez en tant que ʻadmin.

spring-security.jpg

La description

applicationContext.xml


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

MySpringSecurityConfig.java


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

MyMethodSecurityService.java


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

--Annotez la méthode à laquelle vous souhaitez appliquer le @ PreAuthorize --Pour value, spécifiez le contrôle d'accès basé sur les expressions de la même manière que pour ʻaccess of <intercept-url>.

Mettez un processus de vérification après la méthode

la mise en oeuvre

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();
        }
    }
}

Les paramètres sont les mêmes que [précédent](# method-security-pre-authorize).

Contrôle de fonctionnement

Accédez à / method-security? Parameter = hoge

Sortie serveur


parameter = hoge

spring-security.jpg

Accédez à / method-security? Parameter = fuga

Sortie serveur


parameter = fuga

spring-security.jpg

La description

MyMethodSecurityService.java


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

--Si vous annotez avec @ PostAuthorize, la vérification sera effectuée après l'exécution de la méthode.

Référencer des arguments de méthode dans une expression

la mise en oeuvre

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();
        }
    }
}

Contrôle de fonctionnement

Accédez à / method-security? StrValue = abc & intValue = 1

spring-security.jpg

Accédez à / method-security? StrValue = aaa & intValue = 1

spring-security.jpg

La description

MyMethodSecurityService.java


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

Comment résoudre les noms de paramètres de méthode

Le nom du paramètre de la méthode ne peut pas être pris par réflexion s'il s'agit de Java 7 ou moins. Par contre, dans le cas de Java 8 ou supérieur, si l'option -parameters est spécifiée au moment de la compilation, les noms de paramètres peuvent être pris par réflexion /api/java/lang/reflect/Parameter.html).

Spring fournit des solutions pour différents noms de paramètres pour gérer ces situations.

Annoter explicitement

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;
    }
}

Une annotation appelée «@ P» est fournie. Vous pouvez maintenant annoter le paramètre et spécifier le nom du paramètre avec value pour obtenir le nom du paramètre via une annotation.

La classe d'implémentation est ʻAnnotationParameterNameDiscoverer`.

Obtenez par réflexion

Disponible pour Java 8 et supérieur lorsqu'il est compilé avec l'option -parameters au moment de la compilation.

La classe d'implémentation est StandardReflectionParameterNameDiscoverer.

Analyser le fichier de classe pour récupérer les noms des paramètres

Pour utiliser cette fonction, il est nécessaire de générer des informations de débogage au moment de la compilation. Plus précisément, il est nécessaire de spécifier au moins «vars» avec l'option «-g».

Au fait, si vous compilez avec Gradle, cette option est activée par défaut, vous pouvez donc utiliser cette fonctionnalité sans vous en soucier.

La classe d'implémentation est LocalVariableTableParameterNameDiscoverer.


Les fonctions ci-dessus sont appliquées dans l'ordre "Annotation" -> "Réflexion" -> "Analyse de fichier de classe", et le nom trouvé en premier est utilisé.

référence

Recommended Posts

Spring Security Usage Memo Method Security
Mémo d'utilisation de Spring Security CSRF
Mémo d'utilisation de Spring Security Run-As
Mémo d'utilisation de Spring Security Remember-Me
Mémo d'utilisation de Spring Security CORS
Test de mémo d'utilisation de Spring Security
Authentification / autorisation de mémo d'utilisation de Spring Security
En-tête de réponse de mémo d'utilisation de Spring Security
Gestion des sessions de mémo d'utilisation de Spring Security
Mémo d'utilisation de Spring Security Basic / mécanisme
Spring Security Usage Memo Domain Object Security (ACL)
Notes d'utilisation de Spring Shell
Mémo de méthode de contrôleur de démarrage à ressort
Mémo d'utilisation de Spring Security: coopération avec Spring MVC et Boot
Mémo rétrospective du printemps
Notes d'utilisation de JavaParser
Notes d'utilisation de WatchService
Mémo d'utilisation PlantUML
Spring Boot + Thymeleaf Boot Strap Méthode d'installation mémo
Notes d'utilisation de JUnit5
Mémo JJUG CCC Printemps 2018
À propos de l'authentification Spring Security
Rédaction de mémo de démarrage de printemps (1)
Mémo d'apprentissage Java (méthode)
Spring Security soulève 403 interdits
Rédaction de mémos de démarrage de printemps (2)
Appelez votre propre méthode avec PreAuthorize dans Spring Security
Série de mémos d'auto-apprentissage Spring Framework_1
Mémo de la méthode d'étude Java Silver
Créer une méthode java [Memo] [java11]
Fonction de connexion avec Spring Security
[Spring Security] Spring Security sur GAE (SE)
Notes sur l'utilisation du plug-in de gestion des dépendances
Essayez d'utiliser Spring Boot Security
Modèle de conception par la méthode Ruby Template Mémo de modèle
Mise en œuvre de la fonction d'authentification avec Spring Security ②
◆ Spring Boot + note de construction de l'environnement gradle
Méthode de résolution d'erreur Spring Boot + PostgreSQL
Implémentez la fonction d'authentification avec Spring Security ③
Mise en œuvre de la fonction d'authentification avec Spring Security ①
Découvrez l'architecture de traitement de l'authentification Spring Security
Mémo après le premier projet Spring-MVC-
Un mémo qui a touché Spring Boot
Mémo de mise à niveau de la version d'introduction approfondie du printemps
Certification / autorisation avec Spring Security & Thymeleaf
Mémo après le premier projet Spring-Database-
[Java] Mémo de méthode de mesure du temps de traitement
Comment utiliser Thymeleaf avec Spring Boot
Développement d'applications Web Spring 5 MVC avec Visual Studio Code Utilisation de Spring Security 1/3 [Préparation]