Java 简单地测试 Spring Boot 安全性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31812054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Testing Spring Boot Security simply
提问by Jakub Koz?owski
I'm struggling with testing access control on URLs protected by Spring Security.
我正在努力测试受 Spring Security 保护的 URL 的访问控制。
The configuration looks like this:
配置如下所示:
http
.authorizeRequests()
.antMatchers("/api/user/**", "/user").authenticated()
.antMatchers("/api/admin/**", "/templates/admin/**", "/admin/**").hasAuthority("ADMIN")
.anyRequest().permitAll();
And the test class looks like this:
测试类如下所示:
package com.kubukoz.myapp;
import com.kubukoz.myapp.config.WebSecurityConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
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 javax.transaction.Transactional;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MyApplication.class, WebSecurityConfig.class})
@WebAppConfiguration
@TransactionConfiguration(defaultRollback = true)
@Transactional(rollbackOn = Exception.class)
public class MyApplicationTests {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Autowired
private FilterChainProxy filterChainProxy;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.dispatchOptions(true)
.addFilters(filterChainProxy)
.build();
}
@Test
public void testAnonymous() throws Exception {
mockMvc.perform(get("/api/user/account")).andExpect(status().is3xxRedirection());
}
@Test
public void testUserAccessForAccount() throws Exception{
mockMvc.perform(get("/api/user/account")).andExpect(status().isOk());
}
}
What's the easiest way to make the last two tests pass? @WithMockUser didn't work.
使最后两个测试通过的最简单方法是什么?@WithMockUser 没有用。
采纳答案by Rob Winch
You should not add the FilterChainProxy directly. Instead, you should apply SecurityMockMvcConfigurers.springSecurity()
as indicated by the reference. An example is included below:
您不应直接添加 FilterChainProxy。相反,您应该SecurityMockMvcConfigurers.springSecurity()
按照参考中的指示进行申请。下面包含一个示例:
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
The result of this is:
这样做的结果是:
- the
FilterChainProxy
is added as aFilter
toMockMvc
(as you did) - the
TestSecurityContextHolderPostProcessor
is added
- 将
FilterChainProxy
被添加为Filter
向MockMvc
(像你一样) - 在
TestSecurityContextHolderPostProcessor
加入
Why is TestSecurityContextHolderPostProcessor
necessary? The reason is that we need to communicate the current user from the test method to the MockHttpServletRequest
that is created. This is necessary because Spring Security's SecurityContextRepositoryFilter
will override any value on SecurityContextHolder
to be the value found by the current SecurityContextRepository
(i.e. the SecurityContext
in HttpSession
).
为什么是TestSecurityContextHolderPostProcessor
必要的?原因是我们需要将当前用户从测试方法传递到MockHttpServletRequest
创建的方法。这是必要的,因为 Spring SecuritySecurityContextRepositoryFilter
将覆盖任何值 onSecurityContextHolder
为当前找到的值SecurityContextRepository
(即SecurityContext
in HttpSession
)。
Update
更新
Remember anything that contains role in the method name automatically prefixes "ROLE_" to the string that was passed in.
请记住,方法名称中包含角色的任何内容都会自动将“ROLE_”作为传入字符串的前缀。
Based on your comment, the problem is you need to either update your configuration to use hasRole instead of hasAuthority (since your annotation is using roles):
根据您的评论,问题是您需要更新配置以使用 hasRole 而不是 hasAuthority (因为您的注释使用角色):
.authorizeRequests()
.antMatchers("/api/user/**", "/user").authenticated()
.antMatchers("/api/admin/**", "/templates/admin/**", "/admin/**").hasRole("ADMIN")
.anyRequest().permitAll();
Alternatively
或者
You in Spring Security 4.0.2+ you can use:
您在 Spring Security 4.0.2+ 中可以使用:
@WithMockUser(authorities="ADMIN")
回答by Jakub Koz?owski
Okay, figured it out.
好的,想通了。
mockMvc.perform(get("/api/user/account")
.with(user("user")))
.andExpect(status().isOk());
It works now.
它现在有效。