我将Spring Security配置为在未经身份验证的用户尝试访问报表时重定向回主页。当我手动测试时,@PreAuthorize
表达式触发AccessDeniedException
,它被Spring的ExceptionTranslationFilter
捕获,导致302 Found重定向到主页。
在我的集成测试中,异常会在ExceptionTranslationFilter
之前的过滤器链中的某处被捕获,并返回403 Forbidden响应。
<!-- Reports configuration -->
<bean id="homeEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/" />
</bean>
<sec:http pattern="/reports/**" entry-point-ref="homeEntryPoint">
<!-- Accessing reports requires having a previous session open so redirect to home -->
<sec:session-management invalid-session-url="/" />
</sec:http>
<!-- Enabled security annotations (i.e. @PreAuthorize) -->
<sec:global-method-security
secured-annotations="enabled" pre-post-annotations="enabled" />
@Resource
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SecurityConfigTest {
@Autowired
protected WebApplicationContext wac;
protected MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders
.webAppContextSetup(this.wac)
.apply(springSecurity())
.build();
}
/**
* Test that the report endpoints will redirect to the home page
*/
@Test
public void testReportLoginRedirect() throws Exception {
String endpoint = "/reports/myReportyWhichRequiresAuth.pdf";
this.mockMvc
.perform(get(endpoint))
.andExpect(status().isFound()) // Error: 403 Forbidden returned
.andExpect(redirectedUrl("/"))
.andReturn();
}
}
为什么测试设置会产生与手动测试不同的结果?
答案 0 :(得分:0)
事实证明,我的手动测试会自动设置一个可接受的application / pdf媒体类型(我假设由于文件扩展名)。在自动测试中,默认媒体类型接受全部。由于响应值不是PDF,因此抛出了HttpMediaTypeNotAcceptableException
,导致DispatcherServlet:processHandlerException
中的异常解析程序返回null ModelAndView并重新抛出原始错误。
要修复测试,我将接受的媒体类型设置为application / pdf并更正了预期的重定向网址(与原始错误无关)。
/**
* Test that the report endpoints will redirect to the home page
*/
@Test
public void testReportLoginRedirect() throws Exception {
String endpoint = "/reports/myReportyWhichRequiresAuth.pdf";
this.mockMvc
.perform(get(endpoint).accept(MediaType.APPLICATION_PDF))
.andExpect(status().isFound())
.andExpect(redirectedUrl("http://localhost/"))
.andReturn();
}