Spring Security Test:测试注释@Secured(或@PreAuthorize)

时间:2016-03-30 14:07:01

标签: spring-security spring-test-mvc

我有一个问题(当然:))。我有一个带有Spring Security和Spring MVC的Spring 4.2应用程序(使用Rest API),我想测试REST方法上存在的注释@Secured(ROLE_FOO)的有效性。 所以我需要为此安装spring-security-test库。好。 然后我跟进一些教程(或文档),如官方的:http://docs.spring.io/autorepo/docs/spring-security/4.1.0.RC1/reference/htmlsingle/

这是我的测试代码(我试图删除所有“不必要的”代码。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
public class UserResourceIntTest {

    private MockMvc restUserMockMvc2;

   @Autowired
    private WebApplicationContext context;

....//Injection, Mocks declarations here

@Before
    public void setup() {




        this.restUserMockMvc2 = MockMvcBuilders.webAppContextSetup(context).apply(SecurityMockMvcConfigurers.springSecurity()).build();



    }


    @Test
    @WithMockUser(roles="ROLE_VIEWER")
    public void testGetUserListe() throws Exception {
        //here getAuthentication() returns null !!! why ???
        SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//      restUserMockMvc2.perform(get("/api/users/liste")
//              .principal(SecurityContextHolder.getContext().getAuthentication()))
//                .accept(MediaType.APPLICATION_JSON))
//                .andExpect(status().isForbidden());
//                .andExpect(content().contentType("application/json"));
    }

这里是我要测试的方法:

@RestController
@RequestMapping("/api")
public class UserResource {

    @RequestMapping(value = "/users/liste", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    @Transactional(readOnly = true)
    @Secured({ AuthoritiesConstants.TC_ADMIN })
    public ResponseEntity<List<ManagedUserDTO>> getUserListe(Pageable pageable, Principal principal) throws URISyntaxException {

        //doSomething...
    }

你能告诉我为什么在考试中,

SecurityContextHolder.getContext().getAuthentication()

返回null? @WithMockUser应自动验证用户(因此主体)

由于

EDIT1:测试的设置部分(仅涉及安全指令):

@Inject
private FilterChainProxy springSecurityFilterChain;

@Inject
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;

@Before
public void setup() {

....

this.restUserMockMvc2 = MockMvcBuilders
                .standaloneSetup(userResource2)
                .alwaysDo(print())              .apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain))
                .setCustomArgumentResolvers(pageableArgumentResolver)
                .build();

...

}

EDIT2:只是要明确类定义:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@TestExecutionListeners(listeners={ServletTestExecutionListener.class,
        DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class,
        WithSecurityContextTestExecutionListener.class})
public class UserResourceIntTest {
}

1 个答案:

答案 0 :(得分:1)

问题是Spring Security的WithSecurityContextTestExecutionListener未被执行,因为@IntegrationTestoverriding the default TestExecutionListeners

您很可能不需要使用@IntegrationTest MockMvc,因此您应该能够完全删除它并解决您的问题。

或者,您可以通过向您的班级明确添加WithSecurityContextTestExecutionListener来解决此问题,例如:

@TestExecutionListeners(listeners = { WithSecurityContextTestExecutionListener.class, IntegrationTestPropertiesListener.class,
        DirtiesContextBeforeModesTestExecutionListener.class,
        DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class, SqlScriptsTestExecutionListener.class })
@IntegrationTest
public class UserResourceIntTest {