如何避免 https spring 安全单元测试的 302 响应?
How to avoid 302 response on https spring security unit test?
我有 java Spring 安全应用程序(使用 jhipster 构建),我正在尝试添加一些单元测试,以根据当前经过身份验证的用户测试逻辑。
为此,我配置了 MockMvc
对象以使用 Web 应用程序上下文和 spring 安全性:
@Test
@Transactional
public void getAllContacts() throws Exception {
restContactMockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
restContactMockMvc.perform(get("/api/contacts")).andExpect(status().isOk());
}
问题是我还将应用程序配置为需要 HTTPS,每当我 运行 这个单元测试时,我都会收到 302 重定向响应,因为它似乎在尝试发送 HTTP 请求而不是HTTPS.
我强制使用 HTTPS 的方式是 SecurityConfiguration.configure(HttpSecurity http)
中的以下行:
if (env.acceptsProfiles("!dev"))http.requiresChannel().anyRequest().requiresSecure();
所以,我的问题是如何让我的单元测试正确地达到 运行?可能是通过发送模拟 HTTPS 请求,或者在 运行 进行单元测试时禁用 HTTPS?
我正在用我已经开始使用的修复程序回答我自己的问题,希望这可以帮助其他人。我仍然愿意接受其他更好的解决方案。
在 SecurityConfiguration.configure(HttpSecurity http)
方法中,我修改了 if 语句,如果我们是 运行 集成测试,则强制 https 跳过它:
if (env.acceptsProfiles("!dev") && !((StandardEnvironment) env).getPropertySources().contains("integrationTest")) {
http.requiresChannel().anyRequest().requiresSecure();
}
使用 Springs MockMvc 东西,您还可以指定要使用 secure(true) 方法发送模拟 HTTPS 请求,如下所示:
restContactMockMvc.perform( get("/api/contacts").secure( true ) ).andExpect( status().isOk() )
除了@rhinds 的正确答案之外,您还可以将此代码添加到您的 @Before
方法中,以使所有调用在默认情况下都是安全的:
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.testSecurityContext;
public class YourTestClass {
@Autowired
private Filter springSecurityFilterChain;
@Autowired
private SecurityTestController securityTestController;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = standaloneSetup(securityTestController)
.addFilters(springSecurityFilterChain)
.defaultRequest(get("/").secure(true).with(testSecurityContext()))
.build();
}
// Your Tests Here
@Test
public void httpsRedirect() throws Exception {
mockMvc.perform(get("/").secure(false))
.andExpect(status().isFound())
.andExpect(result -> StringUtils.isNotEmpty(result.getResponse().getHeader("Location")))
.andExpect(result -> result.getResponse().getHeader("Location").startsWith("https://"));
}
}
我有 java Spring 安全应用程序(使用 jhipster 构建),我正在尝试添加一些单元测试,以根据当前经过身份验证的用户测试逻辑。
为此,我配置了 MockMvc
对象以使用 Web 应用程序上下文和 spring 安全性:
@Test
@Transactional
public void getAllContacts() throws Exception {
restContactMockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
restContactMockMvc.perform(get("/api/contacts")).andExpect(status().isOk());
}
问题是我还将应用程序配置为需要 HTTPS,每当我 运行 这个单元测试时,我都会收到 302 重定向响应,因为它似乎在尝试发送 HTTP 请求而不是HTTPS.
我强制使用 HTTPS 的方式是 SecurityConfiguration.configure(HttpSecurity http)
中的以下行:
if (env.acceptsProfiles("!dev"))http.requiresChannel().anyRequest().requiresSecure();
所以,我的问题是如何让我的单元测试正确地达到 运行?可能是通过发送模拟 HTTPS 请求,或者在 运行 进行单元测试时禁用 HTTPS?
我正在用我已经开始使用的修复程序回答我自己的问题,希望这可以帮助其他人。我仍然愿意接受其他更好的解决方案。
在 SecurityConfiguration.configure(HttpSecurity http)
方法中,我修改了 if 语句,如果我们是 运行 集成测试,则强制 https 跳过它:
if (env.acceptsProfiles("!dev") && !((StandardEnvironment) env).getPropertySources().contains("integrationTest")) {
http.requiresChannel().anyRequest().requiresSecure();
}
使用 Springs MockMvc 东西,您还可以指定要使用 secure(true) 方法发送模拟 HTTPS 请求,如下所示:
restContactMockMvc.perform( get("/api/contacts").secure( true ) ).andExpect( status().isOk() )
除了@rhinds 的正确答案之外,您还可以将此代码添加到您的 @Before
方法中,以使所有调用在默认情况下都是安全的:
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.testSecurityContext;
public class YourTestClass {
@Autowired
private Filter springSecurityFilterChain;
@Autowired
private SecurityTestController securityTestController;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = standaloneSetup(securityTestController)
.addFilters(springSecurityFilterChain)
.defaultRequest(get("/").secure(true).with(testSecurityContext()))
.build();
}
// Your Tests Here
@Test
public void httpsRedirect() throws Exception {
mockMvc.perform(get("/").secure(false))
.andExpect(status().isFound())
.andExpect(result -> StringUtils.isNotEmpty(result.getResponse().getHeader("Location")))
.andExpect(result -> result.getResponse().getHeader("Location").startsWith("https://"));
}
}