[JAVA] Test de mémo d'utilisation de Spring Security

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

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

Test de sécurité de printemps

Spring Security fournit un mécanisme pour prendre en charge les tests avec JUnit.

Par exemple, l'utilisateur utilisé pour les tests peut être fixé et l'autorité peut être spécifiée.

Hello World

la mise en oeuvre

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    testCompile 'junit:junit:4.12'★ Ajout
    testCompile 'org.springframework.security:spring-security-test:4.2.1.RELEASE'★ Ajout
}

MyTestService.java


package sample.spring.security.test;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;

public class MyTestService {
    
    @PreAuthorize("authenticated")
    public String getMessage() {
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        return "Hello " + name;
    }
}

--Classe à tester --Vérifiez si authentifié avec @PreAuthorize ()

namespace

src/test/resources/test-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.test.MyTestService" />
    
</beans>

--Fichier de configuration Spring pour les tests

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {
    
    @Autowired
    private MyTestService service;

    @Test(expected = AuthenticationException.class)
    public void test_getMessage_no_authentication() throws Exception {
        // exercise
        this.service.getMessage();
    }

    @Test
    @WithMockUser(username = "hoge")
    public void test_getMessage() throws Exception {
        // exercise
        String message = this.service.getMessage();
        
        // verify
        Assert.assertEquals("Hello hoge", message);
    }
}

Java Configuration

MyTestSpringSecurityConfig.java


package sample.spring.security.test;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class MyTestSpringSecurityConfig {
    
    @Bean
    public MyTestService myTestService() {
        return new MyTestService();
    }
}

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=MyTestSpringSecurityConfig.class)
public class MyTestServiceTest {
    
    @Autowired
    private MyTestService service;

    @Test(expected = AuthenticationException.class)
    public void test_getMessage_no_authentication() throws Exception {
        // exercise
        this.service.getMessage();
    }

    @Test
    @WithMockUser(username = "hoge")
    public void test_getMessage() throws Exception {
        // exercise
        String message = this.service.getMessage();

        // verify
        Assert.assertEquals("Hello hoge", message);
    }
}

--C'est également la même chose que xml sauf que la classe de configuration est chargée avec @ ContextConfiguration.

Contrôle de fonctionnement

Si vous exécutez chacun d'eux, le test réussira.

La description

Paramètres du test de ressort

MyTestServiceTest.java


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")

Spécifier un utilisateur fictif

MyTestServiceTest.java


    @Test
    @WithMockUser(username = "hoge")
    public void test_getMessage() throws Exception {

Annotation

Des informations arbitraires peuvent être définies dans le SecurityContext sous test par une annotation.

@WithMockUser

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {
    
    @Test
    @WithMockUser
    public void test() throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message = "class = " + auth.getClass() + "\n" +
                         "name = " + auth.getName() + "\n" +
                         "credentials = " + auth.getCredentials() + "\n" +
                         "authorities = " + auth.getAuthorities() + "\n" +
                         "principal = " + auth.getPrincipal() + "\n" +
                         "details = " + auth.getDetails();

        System.out.println(message);
    }
}

** Résultat d'exécution **

class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = user
credentials = password
authorities = [ROLE_USER]
principal = org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER
details = null

--Lors de l'utilisation de @ WithMockUser, les informations utilisateur fictives sont stockées dans SecurityContext. --Si rien n'est spécifié, il a les informations suivantes par défaut. --L'utilisateur est ʻutilisateur`

Définir le nom d'utilisateur

MyTestServiceTest.java


    @Test
    @WithMockUser("test-user")
    public void test() throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message = "class = " + auth.getClass() + "\n" +
                         "name = " + auth.getName() + "\n" +
                         "credentials = " + auth.getCredentials() + "\n" +
                         "authorities = " + auth.getAuthorities() + "\n" +
                         "principal = " + auth.getPrincipal() + "\n" +
                         "details = " + auth.getDetails();

        System.out.println(message);
    }

** Résultat d'exécution **

class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = test-user
credentials = password
authorities = [ROLE_USER]
principal = org.springframework.security.core.userdetails.User@b6e8d426: Username: test-user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER
details = null

--La chaîne de caractères définie dans value est utilisée comme nom d'utilisateur --Il est également possible de spécifier avec ʻusername au lieu de value`

Définir le rôle

MyTestServiceTest.java


    @Test
    @WithMockUser(
        username="test-user",
        roles={"FOO", "BAR"}
    )
    public void test() throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message = "class = " + auth.getClass() + "\n" +
                         "name = " + auth.getName() + "\n" +
                         "credentials = " + auth.getCredentials() + "\n" +
                         "authorities = " + auth.getAuthorities() + "\n" +
                         "principal = " + auth.getPrincipal() + "\n" +
                         "details = " + auth.getDetails();

        System.out.println(message);
    }

** Résultat d'exécution **

class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = test-user
credentials = test-pass
authorities = [ROLE_BAR, ROLE_FOO]
principal = org.springframework.security.core.userdetails.User@b6e8d426: Username: test-user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_BAR,ROLE_FOO
details = null

Définir les autorisations

MyTestServiceTest.java


    @Test
    @WithMockUser(
        username="test-user",
        authorities={"FOO", "BAR"}
    )
    public void test() throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message = "class = " + auth.getClass() + "\n" +
                         "name = " + auth.getName() + "\n" +
                         "credentials = " + auth.getCredentials() + "\n" +
                         "authorities = " + auth.getAuthorities() + "\n" +
                         "principal = " + auth.getPrincipal() + "\n" +
                         "details = " + auth.getDetails();

        System.out.println(message);
    }

** Résultat d'exécution **

class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = test-user
credentials = password
authorities = [BAR, FOO]
principal = org.springframework.security.core.userdetails.User@b6e8d426: Username: test-user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO
details = null

Définissez un mot de passe

MyTestServiceTest.java


    @Test
    @WithMockUser(password="test-pass")
    public void test() throws Exception {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message = "class = " + auth.getClass() + "\n" +
                         "name = " + auth.getName() + "\n" +
                         "credentials = " + auth.getCredentials() + "\n" +
                         "authorities = " + auth.getAuthorities() + "\n" +
                         "principal = " + auth.getPrincipal() + "\n" +
                         "details = " + auth.getDetails();

        System.out.println(message);
    }

** Résultat d'exécution **

class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = user
credentials = test-pass
authorities = [ROLE_USER]
principal = org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER
details = null

@WithAnonymousUser

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@WithMockUser
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {

    @Test
    @WithAnonymousUser
    public void testAnonymous() throws Exception {
        this.printAuthentication("testAnonymous");
    }
    
    @Test
    public void testDefault() throws Exception {
        this.printAuthentication("testDefault");
    }

    private void printAuthentication(String testMethodName) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message =
                "[" + testMethodName + "]\n" +
                "class = " + auth.getClass() + "\n" +
                "name = " + auth.getName() + "\n" +
                "credentials = " + auth.getCredentials() + "\n" +
                "authorities = " + auth.getAuthorities() + "\n" +
                "principal = " + auth.getPrincipal() + "\n" +
                "details = " + auth.getDetails();

        System.out.println(message);
    }
}

** Résultat d'exécution **

[testAnonymous]
class = class org.springframework.security.authentication.AnonymousAuthenticationToken
name = anonymous
credentials = 
authorities = [ROLE_ANONYMOUS]
principal = anonymous
details = null

[testDefault]
class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = user
credentials = password
authorities = [ROLE_USER]
principal = org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER
details = null

--Annoter avec @ WithAnonymousUser pour utiliser un utilisateur anonyme

@WithUserDetails

MyUserDetailsService.java


package sample.spring.security.service;

import org.springframework.security.core.GrantedAuthority;
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;

import java.util.Collection;

public class MyUserDetailsService implements UserDetailsService {
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return new MyUser(username, "test-password", AuthorityUtils.createAuthorityList("FOO", "BAR"));
    }
    
    private static class MyUser extends User {
        private MyUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
            super(username, password, authorities);
        }
    }
}

test-applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">

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

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {

    @Test
    @WithUserDetails
    public void test() throws Exception {
        this.printAuthentication("test");
    }

    private void printAuthentication(String testMethodName) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message =
                "[" + testMethodName + "]\n" +
                "class = " + auth.getClass() + "\n" +
                "name = " + auth.getName() + "\n" +
                "credentials = " + auth.getCredentials() + "\n" +
                "authorities = " + auth.getAuthorities() + "\n" +
                "principal = " + auth.getPrincipal() + "\n" +
                "details = " + auth.getDetails();

        System.out.println(message);
    }
}

** Résultat d'exécution **

[test]
class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = user
credentials = test-password
authorities = [BAR, FOO]
principal = sample.spring.security.service.MyUserDetailsService$MyUser@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO
details = null

@WithSecurityContext

MyTestUser.java


package sample.spring.security.test;

import org.springframework.security.test.context.support.WithSecurityContext;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@WithSecurityContext(factory=MyTestUserFactory.class)
public @interface MyTestUser {
    String name();
    String pass();
    String authority();
}

MyTestUserFactory.java


package sample.spring.security.test;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.test.context.support.WithSecurityContextFactory;

public class MyTestUserFactory implements WithSecurityContextFactory<MyTestUser> {
    
    @Override
    public SecurityContext createSecurityContext(MyTestUser annotation) {
        SecurityContext context = SecurityContextHolder.createEmptyContext();

        String name = annotation.name();
        String pass = annotation.pass();
        String authority = annotation.authority();

        UserDetails user = new User(name, pass, AuthorityUtils.createAuthorityList(authority));
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                                            user, user.getPassword(), user.getAuthorities());
        
        context.setAuthentication(authentication);

        return context;
    }
}

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {

    @Test
    @MyTestUser(name="foo", pass="FOO", authority="TEST_FOO")
    public void test() throws Exception {
        this.printAuthentication("test");
    }

    private void printAuthentication(String testMethodName) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message =
                "[" + testMethodName + "]\n" +
                "class = " + auth.getClass() + "\n" +
                "name = " + auth.getName() + "\n" +
                "credentials = " + auth.getCredentials() + "\n" +
                "authorities = " + auth.getAuthorities() + "\n" +
                "principal = " + auth.getPrincipal() + "\n" +
                "details = " + auth.getDetails();

        System.out.println(message);
    }
}

** Résultat d'exécution **

[test]
class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = foo
credentials = FOO
authorities = [TEST_FOO]
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: TEST_FOO
details = null

MyTestUser.java


@WithSecurityContext(factory=MyTestUserFactory.class)
public @interface MyTestUser {

--Créez une annotation arbitraire et annotez avec @ WithSecurityContext --Spécifiez l'objet Class de la classe qui implémente l'interface WithSecurityContextFactory dans factory.

MyTestUserFactory.java


package sample.spring.security.test;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.test.context.support.WithSecurityContextFactory;

public class MyTestUserFactory implements WithSecurityContextFactory<MyTestUser> {
    
    @Override
    public SecurityContext createSecurityContext(MyTestUser annotation) {
        SecurityContext context = SecurityContextHolder.createEmptyContext();

        ...

        return context;
    }
}

--Une classe d'usine créée en implémentant l'interface WithSecurityContextFactory <T> --Dans la variable de type T, spécifiez le type d'annotation gérée par la classe d'usine.

MyTestServiceTest.java


    @MyTestUser(name="foo", pass="FOO", authority="TEST_FOO")
    public void test() throws Exception {

Injecter des beans gérés par des conteneurs dans des classes d'usine

MyTestUserFactory.java


public class MyTestUserFactory implements WithSecurityContextFactory<MyTestUser> {
    private UserDetailsService userDetailsService;

    @Autowired
    public MyTestUserFactory(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

Méta-annotation

HogeUser.java


package sample.spring.security.test;

import org.springframework.security.test.context.support.WithMockUser;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@WithMockUser(username = "hoge", authorities = {"FOO", "BAR"})
public @interface HogeUser {
}

MyTestServiceTest.java


package sample.spring.security.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
public class MyTestServiceTest {

    @Test
    @HogeUser
    public void test() throws Exception {
        this.printAuthentication("test");
    }

    private void printAuthentication(String testMethodName) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String message =
                "[" + testMethodName + "]\n" +
                "class = " + auth.getClass() + "\n" +
                "name = " + auth.getName() + "\n" +
                "credentials = " + auth.getCredentials() + "\n" +
                "authorities = " + auth.getAuthorities() + "\n" +
                "principal = " + auth.getPrincipal() + "\n" +
                "details = " + auth.getDetails();

        System.out.println(message);
    }
}

** Résultat d'exécution **

[test]
class = class org.springframework.security.authentication.UsernamePasswordAuthenticationToken
name = hoge
credentials = password
authorities = [BAR, FOO]
principal = org.springframework.security.core.userdetails.User@30f425: Username: hoge; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO
details = null

Intégration avec Spring MVC

Hello World La mise en oeuvre

build.gradle


dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
    compile 'org.springframework:spring-webmvc:4.2.1.RELEASE'★ Ajout
    testCompile 'junit:junit:4.12'
    testCompile 'org.springframework.security:spring-security-test:4.2.1.RELEASE'
}

MyMvcController.java


package sample.spring.security.control;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/mvc")
public class MyMvcController {
    
    @GetMapping
    public String hello() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("auth.name = " + auth.getName());
        
        return "test";
    }
}

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

    <bean class="sample.spring.security.control.MyMvcController" />

    <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 />
</beans>

--Déclaration simple pour Spring Security et déclaration Bean pour MyMvcController

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(SecurityMockMvcConfigurers.springSecurity())
                    .build();
    }

    @Test
    public void unauthorized() throws Exception {
        MvcResult mvcResult = this.mvc.perform(get("/mvc")).andReturn();
        this.printResponse("unauthorized", mvcResult);
    }

    @Test
    public void authorized() throws Exception {
        MvcResult mvcResult = this.mvc.perform(get("/mvc").with(user("foo"))).andReturn();
        this.printResponse("authorized", mvcResult);
    }
    
    private void printResponse(String method, MvcResult result) throws Exception {
        MockHttpServletResponse response = result.getResponse();
        int status = response.getStatus();
        String locationHeader = response.getHeader("Location");

        System.out.println("[" + method + "]\n" +
                           "status : " + status + "\n" +
                           "Location : " + locationHeader);
    }
}

--Il existe deux méthodes de test, «non autorisées» et «autorisées».

** Résultat d'exécution **

auth.name = foo
[authorized]
status : 200
Location : null

[unauthorized]
status : 302
Location : http://localhost/login

--ʻAuthorized peut être exécuté par le contrôleur et le nom d'utilisateur est affiché. --ʻUnauthorized renvoie un statut de "302" et vous invite à vous rediriger vers l'écran de connexion

La description

MyMvcControllerTest.java


import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(SecurityMockMvcConfigurers.springSecurity())
                    .build();
    }

MyMvcControllerTest.java



import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;.

...

    @Test
    public void unauthorized() throws Exception {
        MvcResult mvcResult = this.mvc.perform(get("/mvc")).andReturn();
        this.printResponse("unauthorized", mvcResult);
    }

    @Test
    public void authorized() throws Exception {
        MvcResult mvcResult = this.mvc.perform(get("/mvc").with(user("foo"))).andReturn();
        this.printResponse("authorized", mvcResult);
    }

--get () est la méthode statique de MockMvcRequestBuilders --ʻUser () ʻest la méthode statique de SecurityMockMvcRequestPostProcessors --Spécifiez le nom de l'utilisateur de connexion lors de l'exécution --Spring MVC Test a un mécanisme pour réécrire une requête et utilise une classe qui implémente l'interface RequestPostProcessor. --Spring Security fournit de nombreuses classes qui implémentent ce RequestPostProcessor pour faciliter la configuration de Spring Security.

CSRF Si la protection CSRF est activée, le jeton doit être inclus dans la demande. Si vous appelez le contrôleur tel quel sans rien faire, une erreur se produira car il n'y a pas de jeton.

Par conséquent, il existe une API pour tester pour réussir la vérification du jeton CSRF.

La mise en oeuvre

test-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 class="sample.spring.security.control.MyMvcController" />

    <sec:http>
        <sec:intercept-url pattern="/login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login />
        <sec:logout />
        <sec:csrf />★ Ajout
    </sec:http>

    <sec:authentication-manager />
</beans>

--Ajoutez <csrf> pour activer la protection CSRF

MyMvcController.java


package sample.spring.security.control;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/mvc")
public class MyMvcController {
    
    @PostMapping
    public String hello() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        System.out.println("auth.name = " + auth.getName());
        
        return "test";
    }
}

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(SecurityMockMvcConfigurers.springSecurity())
                    .build();
    }

    @Test
    public void noToken() throws Exception {
        MvcResult mvcResult = this.mvc.perform(
            post("/mvc")
            .with(user("foo"))
        ).andReturn();
        
        this.printResponse("noToken", mvcResult);
    }

    @Test
    public void useToken() throws Exception {
        MvcResult mvcResult = this.mvc.perform(
            post("/mvc")
            .with(user("bar"))
            .with(csrf())
        ).andReturn();
        
        this.printResponse("useToken", mvcResult);
    }
    
    private void printResponse(String method, MvcResult result) throws Exception {
        MockHttpServletResponse response = result.getResponse();
        int status = response.getStatus();
        String errorMessage = response.getErrorMessage();

        System.out.println("[" + method + "]\n" +
                           "status : " + status + "\n" +
                           "errorMessage : " + errorMessage);
    }
}

** Résultat d'exécution **

[noToken]
status : 403
errorMessage : Could not verify the provided CSRF token because your session was not found.

auth.name = bar
[useToken]
status : 200
errorMessage : null

--noToken () est bloqué dans la vérification des jetons CSRF et entraîne une erreur --ʻUseToken () `réussit à exécuter la méthode du contrôleur

La description

MyMvcControllerTest.java


    @Test
    public void noToken() throws Exception {
        MvcResult mvcResult = this.mvc.perform(
            post("/mvc")
            .with(user("foo"))
        ).andReturn();
        
        this.printResponse("noToken", mvcResult);
    }

    @Test
    public void useToken() throws Exception {
        MvcResult mvcResult = this.mvc.perform(
            post("/mvc")
            .with(user("bar"))
            .with(csrf())
        ).andReturn();
        
        this.printResponse("useToken", mvcResult);
    }

--Utilisez la méthode csrf () pour inclure le jeton CSRF dans la demande de test.

Définir un jeton illégal

La mise en oeuvre

MyMvcControllerTest.java


    @Test
    public void useInvalidToken() throws Exception {
        MvcResult mvcResult = this.mvc.perform(
            post("/mvc")
            .with(user("bar"))
            .with(csrf().useInvalidToken())
        ).andReturn();
        
        this.printResponse("useInvalidToken", mvcResult);
    }

** Résultat d'exécution **

[useInvalidToken]
status : 403
errorMessage : Invalid CSRF Token 'invalidd19aed27-65e2-4cf6-9456-157e1f29c984' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

La description

--csrf (). useInvalidToken ()définira un jeton invalide

Spécification utilisateur

Il existe deux façons de spécifier l'utilisateur:

--Méthode utilisant RequestPostProcessor --Méthode utilisant des annotations

Méthode utilisant RequestPostProcessor

Une méthode utilisant le point d'extension de la requête fourni par Spring MVC Test. Par rapport à la spécification par annotation, il semble que la particularité est qu'elle puisse être spécifiée dynamiquement.

La mise en oeuvre

MyMvcController.java


package sample.spring.security.control;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.stream.Collectors;

@Controller
@RequestMapping("/mvc")
public class MyMvcController {
    
    @GetMapping
    public String hello() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        String name = auth.getName();
        Object credentials = auth.getCredentials();
        Object principal = auth.getPrincipal();
        String authorities = auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(", "));

        System.out.println(
            "name = " + name + "\n" + 
            "credentials = " + credentials + "\n" + 
            "authorities = " + authorities + "\n" +
            "principal = " + principal
        );
        
        return "test";
    }
}

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.List;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    private static final String USERNAME = "foo";
    private static final String PASSWORD = "test-pass";
    private static final List<GrantedAuthority> AUTHORITIES = AuthorityUtils.createAuthorityList("FOO", "BAR");
    
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(SecurityMockMvcConfigurers.springSecurity())
                    .build();
    }

    @Test
    public void withUser() throws Exception {
        System.out.println("[withUser]");
        this.mvc.perform(
            get("/mvc").with(user(USERNAME))
        );
    }

    @Test
    public void customized() throws Exception {
        System.out.println("[customized]");
        this.mvc.perform(
            get("/mvc").with(
                user(USERNAME)
                .password(PASSWORD)
                .authorities(AUTHORITIES)
            )
        );
    }

    @Test
    public void userDetails() throws Exception {
        System.out.println("[userDetails]");
        UserDetails user = this.createUserDetails();

        this.mvc.perform(
            get("/mvc").with(user(user))
        );
    }

    @Test
    public void withAnonymous() throws Exception {
        System.out.println("[withAnonymous]");

        this.mvc.perform(
            get("/mvc").with(anonymous())
        );
    }

    @Test
    public void withAuthentication() throws Exception {
        System.out.println("[withAuthentication]");
        Authentication auth = this.createAuthentication();

        this.mvc.perform(
            get("/mvc").with(authentication(auth))
        );
    }

    @Test
    public void withSecurityContext() throws Exception {
        System.out.println("[withAuthentication]");
        Authentication auth = this.createAuthentication();
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        context.setAuthentication(auth);

        this.mvc.perform(
            get("/mvc").with(securityContext(context))
        );
    }

    private UserDetails createUserDetails() {
        return new User(USERNAME, PASSWORD, AUTHORITIES);
    }
    
    private Authentication createAuthentication() {
        UserDetails user = this.createUserDetails();
        return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
    }
}

** Résultat d'exécution **

[withUser]
name = foo
credentials = password
authorities = ROLE_USER
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER

[customized]
name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

[userDetails]
name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

[withAnonymous]
name = anonymous
credentials = 
authorities = ROLE_ANONYMOUS
principal = anonymous

[withAuthentication]
name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

[withSecurityContext]
name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

La description

--Si seul user (String) ʻest spécifié, seul le nom d'utilisateur aura la valeur spécifiée.

Définir les informations utilisateur par défaut

La mise en oeuvre

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .defaultRequest(get("/")
                        .with(
                            user("foo")
                            .password("test-pass")
                            .authorities(AuthorityUtils.createAuthorityList("FOO", "BAR"))
                        )
                    )
                    .build();
    }

    @Test
    public void test() throws Exception {
        this.mvc.perform(get("/mvc"));
    }
}

** Résultat d'exécution **

name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

La description

MyMvcControllerTest.java


    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .defaultRequest(get("/")
                        .with(
                            user("foo")
                            .password("test-pass")
                            .authorities(AuthorityUtils.createAuthorityList("FOO", "BAR"))
                        )
                    )
                    .build();
    }

--Si vous spécifiez les informations utilisateur avec defaultRequest () lors de la création de MockMvc, vous pouvez l'utiliser comme paramètre par défaut.

Résumer les définitions d'utilisateurs fréquemment utilisées

La mise en oeuvre

MyMockUserPostProcessors.java


package sample.spring.security.test;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.test.web.servlet.request.RequestPostProcessor;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;

public class MyMockUserPostProcessors {
    
    public static RequestPostProcessor hoge() {
        return user("hoge")
                .password("test-pass")
                .authorities(AuthorityUtils.createAuthorityList("FOO", "BAR"));
    }
}

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static sample.spring.security.test.MyMockUserPostProcessors.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }
    
    @Test
    public void test() throws Exception {
        this.mvc.perform(get("/mvc").with(hoge()));
    }
}

** Résultat d'exécution **

name = hoge
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@30f425: Username: hoge; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

La description

MyMockUserPostProcessors.java


    public static RequestPostProcessor hoge() {
        return user("hoge")
                .password("test-pass")
                .authorities(AuthorityUtils.createAuthorityList("FOO", "BAR"));
    }

Méthode utilisant des annotations

La méthode utilisant l'annotation telle que «@ WithMockUser» écrite au début.

Comparé à la méthode utilisant RequestPostProcessor, ** lorsque le changement dynamique n'est pas nécessaire ** les annotations aux méthodes et aux classes sont suffisantes, et je pense qu'elle a une fonctionnalité plus déclarative. Après cela, il est possible de partager la méthode de spécification des utilisateurs fictifs avec des tests autres que MVC.

La mise en oeuvre

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }

    @Test
    @WithMockUser(username="foo", password="test-pass", authorities={"FOO", "BAR"})
    public void test() throws Exception {
        this.mvc.perform(get("/mvc"));
    }
}

** Résultat d'exécution **

name = foo
credentials = test-pass
authorities = BAR, FOO
principal = org.springframework.security.core.userdetails.User@18cc6: Username: foo; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: BAR,FOO

La description

Connexion par formulaire

La mise en oeuvre

test-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 class="sample.spring.security.control.MyMvcController" />

    <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="password" authorities="FOO" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }

    @Test
    public void test() throws Exception {
        MvcResult result = this.mvc.perform(formLogin()).andReturn();
        this.printResponse("test", result);
    }

    private void printResponse(String method, MvcResult result) throws Exception {
        MockHttpServletResponse response = result.getResponse();
        int status = response.getStatus();
        String location = response.getHeader("Location");

        System.out.println("[" + method + "]\n" +
                "status : " + status + "\n" +
                "location : " + location;
    }
}

** Résultat d'exécution **

[test]
status : 302
location : /

La description

test-applicationContext.xml


    <sec:user name="user" password="password1" authorities="FOO" />

MyMvcControllerTest.java


    @Test
    public void test() throws Exception {
        MvcResult result = this.mvc.perform(formLogin()).andReturn();
        this.printResponse("test", result);
    }

Spécifiez divers paramètres

La mise en oeuvre

test-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 class="sample.spring.security.control.MyMvcController" />

    <sec:http>
        <sec:intercept-url pattern="/do-login" access="permitAll" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />
        <sec:form-login login-processing-url="/do-login"
                        username-parameter="login-id"
                        password-parameter="pass" />
        <sec:logout />
    </sec:http>

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

--Définissez l'URL de connexion et les noms de paramètre du nom d'utilisateur et du mot de passe sur des valeurs différentes de la valeur par défaut

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }

    @Test
    public void test() throws Exception {
        MvcResult result = this.mvc.perform(
            formLogin("/do-login")
            .userParameter("login-id")
            .passwordParam("pass")
            .user("user")
            .password("password")
        ).andReturn();

        this.printResponse("test", result);
    }

    private void printResponse(String method, MvcResult result) throws Exception {
        ...
    }
}

** Résultat d'exécution **

[test]
status : 302
location : /

La description

MyMvcControllerTest.java


    @Test
    public void test() throws Exception {
        MvcResult result = this.mvc.perform(
            formLogin("/do-login")
            .userParameter("login-id")
            .passwordParam("pass")
            .user("user")
            .password("password")
        ).andReturn();

        this.printResponse("test", result);
    }

--Si le chemin de traitement de connexion est différent du chemin par défaut (/ login), vous pouvez spécifier le chemin avec l'argument de formLogin (). --Peut également être spécifié avec loginProcessingUrl () --Si le nom du paramètre du nom d'utilisateur est différent de celui par défaut (ʻusername), vous pouvez le spécifier avec ʻuserParameter () . --Si le nom du paramètre de mot de passe est différent de la valeur par défaut (password), vous pouvez le spécifier avec passwordParam ().

Se déconnecter

La mise en oeuvre

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }

    @Test
    public void test() throws Exception {
        MvcResult result = this.mvc.perform(logout()).andReturn();
        this.printResponse("test", result);
    }

    private void printResponse(String method, MvcResult result) throws Exception {
        ...
    }
}

** Résultat d'exécution **

[test]
status : 302
location : /login?logout

La description

Vérification des informations d'identification après la connexion

La mise en oeuvre

test-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 class="sample.spring.security.control.MyMvcController" />

    <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="foo" password="foo" authorities="FOO, BAR" />
                <sec:user name="fizz" password="fizz" authorities="ROLE_FIZZ, ROLE_BUZZ" />
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

--Définissez les autorisations FOO et BAR pour l'utilisateur foo --Définissez les rôles de ROLE_FIZZ et ROLE_BUZZ pour l'utilisateur fizz

MyMvcControllerTest.java


package sample.spring.security.test;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.List;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
@WebAppConfiguration
public class MyMvcControllerTest {
    @Autowired
    private WebApplicationContext context;
    
    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        this.mvc = MockMvcBuilders
                    .webAppContextSetup(this.context)
                    .apply(springSecurity())
                    .build();
    }

    @Test
    public void test_unauthenticated() throws Exception {
        this.mvc.perform(formLogin().user("foo").password("invalid"))
                .andExpect(unauthenticated());
    }

    @Test
    public void test_authenticated() throws Exception {
        this.mvc.perform(formLogin().user("foo").password("foo"))
                .andExpect(authenticated());
    }

    @Test
    public void test_withUsername() throws Exception {
        this.mvc.perform(formLogin().user("foo").password("foo"))
                .andExpect(authenticated().withUsername("foo"));
    }

    @Test
    public void test_withAuthorities() throws Exception {
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("FOO", "BAR");
        
        this.mvc.perform(formLogin().user("foo").password("foo"))
                .andExpect(authenticated().withAuthorities(authorities));
    }

    @Test
    public void test_combine() throws Exception {
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("FOO", "BAR");
        
        this.mvc.perform(formLogin().user("foo").password("foo"))
                .andExpect(authenticated().withUsername("foo").withAuthorities(authorities));
    }

    @Test
    public void test_withRoles() throws Exception {
        this.mvc.perform(formLogin().user("fizz").password("fizz"))
                .andExpect(authenticated().withRoles("FIZZ", "BUZZ"));
    }
}

** Résultat d'exécution **

Tous les tests réussissent

La description

MyMvcControllerTest.java


    @Test
    public void test_unauthenticated() throws Exception {
        this.mvc.perform(formLogin().user("foo").password("invalid"))
                .andExpect(unauthenticated());
    }
Nom de la méthode Contenu de la vérification
unauthenticated() Vérifiez que vous n'êtes pas authentifié
authenticated() Vérifiez que vous êtes authentifié
pour çawithUsername()Une vérification détaillée est possible en continuant comme
withUsername(String) Valider le nom d'utilisateur
withAuthorities(Collection<? extends GrantedAuthority>) Valider l'autorité accordée
withRoles(String...) Validez le rôle attribué

MyMvcControllerTest.java


    @Test
    public void test_combine() throws Exception {
        List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("FOO", "BAR");
        
        this.mvc.perform(formLogin().user("foo").password("foo"))
                .andExpect(authenticated().withUsername("foo").withAuthorities(authorities));
    }

--Plusieurs withUsername () et withAuthorities () peuvent être combinés

référence

Recommended Posts

Test de mémo d'utilisation de Spring Security
Mémo d'utilisation de Spring Security CSRF
Mémo d'utilisation de Spring Security Run-As
Spring Security Usage Memo Method Security
Mémo d'utilisation de Spring Security Remember-Me
Mémo d'utilisation de Spring Security CORS
Gestion des sessions de mémo d'utilisation de Spring Security
Spring Security Usage Memo Domain Object Security (ACL)
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
Le test Spring Boot @WebMvcTest active la sécurité par défaut de Spring Security
Notes d'utilisation de WatchService
Mémo d'utilisation PlantUML
Notes d'utilisation de JUnit5
À propos de l'authentification Spring Security
Spring Security soulève 403 interdits
Rédaction de mémos de démarrage de printemps (2)
[Notes personnelles] À propos du framework Spring
Mémo de participation au printemps JJUG CCC 2018
[Spring] Test de sortie d'exception du contrôleur
Série de mémos d'auto-apprentissage Spring Framework_1
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
Test de validation d'élément unique de printemps
Mémo de méthode de contrôleur de démarrage à ressort
Mise en œuvre de la fonction d'authentification avec Spring Security ②
Comment faire un test unitaire de Spring AOP
Mémo d'utilisation de JCA (Java Encryption Architecture)
Implémentez la fonction d'authentification avec Spring Security ③
Tutoriel Spring Boot à l'aide de l'authentification Spring Security
Écrire du code de test avec Spring Boot
cadre de printemps Mémo d'étude simple (2): AOP
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-
Utiliser DBUnit pour le test 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-
Contrôleur de cadre de test Spring avec Junit
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]