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
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
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 ()
actuelle et renvoyez-la sous la forme
"Hello Name" `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);
}
}
@ ContextConfiguration
est lancée quand
getMessage () ʻest exécuté sans spécifier @ WithMockUser
@ WithMockUser
, vous testez que le message de retour est construit avec la chaîne spécifiée par @ WithMockUser
.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
.
Si vous exécutez chacun d'eux, le test réussira.
MyTestServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-applicationContext.xml")
pour le test. --Dans
@ ContextConfiguration, spécifiez les paramètres Spring à utiliser pour les tests. --Passez l'emplacement sur le chemin de classe xml pour l'espace de noms ou sur l'objet
Class` de la classe de configuration pour la configuration JavaMyTestServiceTest.java
@Test
@WithMockUser(username = "hoge")
public void test_getMessage() throws Exception {
@ WithMockUser
, vous pouvez spécifier les informations utilisateur (ʻAuthentication) qui seront utilisées pendant l'exécution du test. --- Puisque username = "hoge"
, ʻAuthentication with username
hogesera utilisé. --Spring Security s'intègre à Spring Test pour définir et effacer les informations
SecurityContextHolder` avant et après le test.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`
password
est utilisé pour implémenter ʻAuthentication
--L'objet ʻUser est utilisé comme principal --ʻUser
est un utilisateur fictif, donc l'utilisateur avec ce nom n'a pas vraiment besoin d'exister
--Il est également possible d'annoter la classe (auquel cas toutes les méthodes utiliseront l'utilisateur fictif)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`
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
roles
, l'autorité qui a automatiquement accordé le préfixe ROLE_
est définie.
--Une erreur se produit lors de la définition avec des "autorités"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
roles
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
password
@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
@ WithMockUser
, le paramètre peut être remplacé en annotant la méthode avec @ WithAnonymousUser
.@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
@ WithUserDetails
, les informations d'authentification seront construites avec les informations utilisateur obtenues à partir de ʻUserDetailsService enregistrées en tant que bean. --Utiliser lorsque vous utilisez vos propres ʻUserDetails
valeur
dans @ WithUserDetails
(la valeur par défaut est" "utilisateur").
--ʻUserDetailsServiceBeanName vous permet de spécifier le bean ʻUserDetailsService
à utiliser@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
SecurityContext
avec n'importe quelle implémentationMyTestUser.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
.
SecurityContext
.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.
createSecurityContext ()
pour créer et renvoyer votre propre SecurityContext
WithSecurityContextTestExecutionListener
générera une fabrique à partir de l'annotation lors de l'exécution du testMyTestServiceTest.java
@MyTestUser(name="foo", pass="FOO", authority="TEST_FOO")
public void test() throws Exception {
SecurityContext
créé dans l'usine spécifiée sera utilisé comme informations d'authentification.MyTestUserFactory.java
public class MyTestUserFactory implements WithSecurityContextFactory<MyTestUser> {
private UserDetailsService userDetailsService;
@Autowired
public MyTestUserFactory(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@ Autowired
peut être omis)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
@ WithMockUser
.@ WithMockUser
défini dans l'annotation personnalisée sera hérité.@ WithMockUser
.
--Bien sûr, vous pouvez l'utiliser avec @ WithUserDetails
ainsi qu'avec @ WithMockUser
.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'
}
spring-webmvc
car il ajoute une implémentation de Spring MVCMyMvcController.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";
}
}
/ mvc
--Output du nom de ʻAuthentication`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».
/ mvc
et imprime l'état HTTP résultant et l'en-tête Location
.** 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();
}
SecurityMockMvcConfigurers.springSecurity ()
dans la méthode setUp ()
.
--Avec ce paramètre, il semble que Spring Security Filter
soit intégré à la maquette MVC et que le traitement de Spring Security fonctionne.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.
SecurityMockMvcRequestPostProcessors
, qui est une collection de méthodes d'usine statiques
, est préparée comme une fenêtre pour utiliser ces classes.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";
}
}
@ PostMapping
--Parce que les mesures CSRF ne sont pas exécutées par la méthode GETMyMvcControllerTest.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.
SecurityMockMvcRequestPostProcessors
--Si vous voulez mettre le jeton dans l'en-tête, utilisez csrf (). AsHeader ()
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
Il existe deux façons de spécifier l'utilisateur:
--Méthode utilisant RequestPostProcessor
--Méthode utilisant des annotations
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.
password
--La seule autorité est ROLE_USER
password (String)
et ʻauthorities (Collection <? Extends GrantedAuthority>) après ʻuser (String)
--Le rôle peut être spécifié avec roles (String ...)
--Si ʻuser (UserDetails) , vous pouvez spécifier ʻUserDetails
directement.avec ʻauthentication (Authentication)
SecurityContext
directement avec securityContext (SecurityContext)
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.
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"));
}
RequestPostProcessor
dans les paramètres fréquemment utilisés avec la méthode static
, il sera plus facile à réutiliser.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
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 : /
/
qui est la destination de transition par défaut après la connexionLa 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);
}
SecurityMockMvcRequestBuilders.formLogin ()
sur perform ()
--Par défaut, la requête suivante est exécutée/ login
--Méthode: POST
--Nom d'utilisateur: ʻutilisateur--Password:
mot de passe --Nom du paramètre d'utilisateur: ʻusername
--Nom du paramètre de mot de passe: password
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 ()
.
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
SecurityMockMvcRequestBuilders.logout ()
à perform ()
exécutera la demande de déconnexion
--Si l'URL de déconnexion est différente de l'URL par défaut (/ logout
), vous pouvez la spécifier comme argument comme logout (" / other-logout-url ")
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());
}
après
perform () . --
SecurityMockMvcResultMatchers fournit des méthodes
statiques` et les utilise.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 ça withUsername() 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
Recommended Posts