[英]Configuration of spring-security doesn't seem to be applied while testing
我已經使用相應的 xml 安全配置配置了一個獨立的 mockMvc,用於測試我用 @PreAuthorize(hasAnyRole('DM,CD')) 注釋的控制器。 但是我的測試結果總是 tatus 200,即使我打電話給一個角色不正確的用戶。 我相信我的 xml 配置遺漏了一些東西,但這只是一個假設。
這是我要測試的控制器:
@RestController
@RequestMapping(value = "/v1/view")
@PreAuthorize("hasAnyRole('Data Manager,Content Designer')")
public class ViewController {
ObjectMapper objectMapper = new JSONMapper();
@Autowired
ViewApiService viewApiService;
//Constructor is needed for tests
ViewController(ViewApiService viewApiService) {
this.viewApiService = viewApiService;
}
public ViewController() {
}
@TruncateLogData
@RequestMapping(method = RequestMethod.GET)
public List<View> getViewItems() throws GenericEngineException {
return viewApiService.getViews();
}
}
這是從主配置中借用的測試 spring-security.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- ****** START Spring Security Configuration *******-->
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<constructor-arg>
<list>
<security:filter-chain pattern="/**" filters="
httpSessionContextIntegrationFilter,
logoutFilter,
basicAuthenticationProcessingFilter,
basicExceptionTranslationFilter,
servletApiBridge,
filterSecurityInterceptor"/>
</list>
</constructor-arg>
</bean>
<!-- ****** START Spring Filters *******-->
<!-- Session integration filter -->
<bean id="httpSessionContextIntegrationFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<constructor-arg>
<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<property name='allowSessionCreation' value='false'/>
</bean>
</constructor-arg>
</bean>
<!-- Basic Authentication processing filter -->
<bean id="basicAuthenticationProcessingFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<constructor-arg ref="authenticationManager"/>
<constructor-arg ref="basicAuthenticationEntryPoint"/>
</bean>
<bean id="basicAuthenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="restapi"/>
</bean>
<!-- Basic Exception translation filter -->
<bean id="basicExceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<constructor-arg ref="basicAuthenticationEntryPoint"/>
</bean>
<!-- Security Context Holder Aware Request filter
Filter that passes wrapped HttpServletRequest which overrides getUserPrincipal() to return current Authentication
-->
<bean id="servletApiBridge" class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter"/>
<!-- Logout filter
Filter that logs the user out in SpringSecurity
-->
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/" index="0"/>
<constructor-arg index="1">
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
</bean>
<!-- ****** END Spring Filters *******-->
<!-- ****** START Spring Security interceptor config *******-->
<!--Define authentication manager, decision manager and secure URL patterns -->
<bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/api/**" access="ROLE_ADMIN"/>
</security:filter-security-metadata-source>
</property>
</bean>
<!-- ****** END Spring Security interceptor config *******-->
<!-- ****** START Spring authentication config *******-->
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref bean="usernamePasswordAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>
<!-- Custom UsernamePassword Authentication Provider -->
<bean id="usernamePasswordAuthenticationProvider" class="com.custom.UsernamePasswordAuthenticationProvider">
<property name="adminLogin" value="true"/>
<property name="customLoginFacade" ref="userSessionFactoryFacade"/>
<property name="additionalRole" value="ROLE_ADMIN"/>
<property name="userInterfaceType" value="API"/>
</bean>
<!-- ****** END Spring authentication config *******-->
<!-- ****** START Spring authorization config *******-->
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
</list>
</constructor-arg>
</bean>
<!-- ****** END Spring authorization config *******-->
<!-- ****** END Spring Security Configuration *******-->
<bean id="userSessionFactoryFacade" class="com.custom.CustomLoginFacadeImpl"/>
</beans>
這是我對控制器的測試:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/testContextConfig.xml", "/spring-security.xml"})
@WebAppConfiguration
public class ViewControllerTest {
private MockMvc mockMvc;
private List<View> viewList;
@Mock
private ViewApiService viewApiService;
@Autowired
private Filter springSecurityFilterChain;
@Before
public void setup() throws JSONException {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(new ViewController(viewApiService))
.addFilter(springSecurityFilterChain)
.setHandlerExceptionResolvers(TestServletExceptionHandler.exceptionResolver())
.build();
viewList = new ArrayList<>();
//initialization of resource to get
viewList.add(new View("1", "view1", content1));
}
@Test
@WithMockUser(username = "testUser3", roles = {"DM"})
public void testIncorrectAccessToControllersMethods() throws Exception {
when(viewApiService.getViews()).thenReturn(viewList);
mockMvc.perform(get("/v1/view"))
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
verify(viewApiService, times(1)).getViews();
}
@Test
@WithMockUser(username = "testUser4", roles = {"OTHER_ROLE"})
public void testDMAccessToControllersMethods() throws Exception {
when(viewApiService.getViews()).thenReturn(viewList);
mockMvc.perform(get("/v1/view"))
.andExpect(status().isUnauthorized());
verify(viewApiService, times(0)).getViews();
}
但結果我得到
ViewControllerTest.testIncorrectAccessToControllersMethods Status expected:<401> but was:<200>
testContextConfig.xml 文件只是一個空上下文。
任何建議將不勝感激
使用相應的注釋更新ViewControllerInterface 的創建沒有幫助,以及添加
<global-method-security pre-post-annotations="enabled" />
到配置文件
更新 2有趣的是,當我嘗試使用mockMvc.perform(get("/v1/view").with(user("name"))).andReturn().getResponse()
構造調用時
我收到
NoSuchMethodError: javax.servlet.http.HttpServletRequest.getServletContext()Ljavax/servlet/ServletContext;
at org.springframework.security.test.web.support.WebTestUtils.findFilter(WebTestUtils.java:120)
所以看起來我的 securityFilterChain 沒有應用於請求(但是,在調試中我可以看到 mockMvc 實例中的所有過濾器)
經過幾個小時的挖掘,原因如下: MockMvcBuilders.standaloneSetup
手動實例化ViewController
(不是使用 Spring,因此不是使用 AOP)。 因此不會攔截 PreAuthorize 並跳過安全檢查。 因此,您可以@Autowire控制器,並把它傳遞給MockMvcBuilders.standaloneSetup
嘲笑你的服務使用@MockBean
,這樣的每個實例ViewApiService
獲取與模擬替代。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.