Spring MockMvcBuilders Security filter

匿名 (未验证) 提交于 2019-12-03 00:52:01

问题:

I have manage to create REST API with spring mvc. My purpose was about to protect a resource with JWToken. Now i am trying to write three Test :
1. Get the Token with granted user/password Authentication Fail => test:OK
2. Get the Token with not granted user/password Authentication success => test:OK
3. Get the protected resource without providing the Token => test:fail because my rest service give the protected resource ....

Here is my REST controller:

    @Component @RestController @RequestMapping(value="/protected") public class HelloWorldRest {     /**      * Logger      */     private static final Logger LOG = LoggerFactory             .getLogger(HelloWorldRest.class);       private static final String template = "Hello, %s!";     private final AtomicLong counter = new AtomicLong();     /**      * permet de générer un token      *       * @param idFonc      */     @RequestMapping(value="/greeting/{name}")     public Greeting greeting(@PathVariable String name) {         LOG.info("Fonction greeting : "+name);     return new Greeting(counter.incrementAndGet(),                         String.format(template, name+ ", je suis Mister Toto"));     }  } 

Here is my test case:

@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(locations = { "/tokenEndPointsTests.xml" }) public class tokenEndPointsTests {  @Autowired private WebApplicationContext context;  private MockMvc mockMvc;  @Autowired private Filter resourceServerFilter;  @Before public void setup() {     // mockMvc = MockMvcBuilders.webAppContextSetup(context).build();     mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilter(resourceServerFilter,"/protected").build(); }  @Test public void testgetToken() throws Exception {     UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(             new Principal() {                 @Override                 public String getName() {                     return "user";                 }              }, null, null);     MvcResult mvcresult = mockMvc             .perform(                     get("/oauth/token").param("client_id", "user")                             .param("client_secret", "password")                             .param("grant_type", "password")                             .param("username", "user")                             .param("password", "password")                             .principal(principal)).andDo(print())             .andExpect(status().isOk()).andReturn();     MockHttpServletRequest mockhttp = mvcresult.getRequest();     System.out.println(mockhttp.toString()); }  @Test public void testgetTokenEchec() throws Exception {     UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(             new Principal() {                 @Override                 public String getName() {                     // c'est le nom de l'user ...                     return "user1";                 }              }, null, null);     MvcResult mvcresult = mockMvc             .perform(                     get("/oauth/token").param("client_id", "user")                             .param("client_secret", "password")                             .param("grant_type", "password")                             .param("username", "user")                             .param("password", "password")                             .principal(principal)).andDo(print())             .andExpect(status().isUnauthorized()).andReturn();     MockHttpServletRequest mockhttp = mvcresult.getRequest();     System.out.println(mockhttp.toString()); }   @Test public void testgetProtectedResource() throws Exception {      MvcResult mvcresult = mockMvc.perform(get("/protected/greeting/toto"))             .andDo(print()).andExpect(status().isUnauthorized())             .andReturn(); }  } 

Here is my tokenEndPointsTests:

    <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  <context:annotation-config /> <context:component-scan base-package="com.sample" /> <mvc:annotation-driven />    <mvc:annotation-driven /> <sec:http pattern="/oauth/token" create-session="stateless"     authentication-manager-ref="authenticationManager">     <sec:intercept-url pattern="/oauth/token" />     <sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />     <sec:custom-filter ref="clientCredentialsTokenEndpointFilter"     before="BASIC_AUTH_FILTER" />     <sec:access-denied-handler ref="oauthAccessDeniedHandler" /> </sec:http>  <sec:http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint">     <sec:anonymous enabled="false" />     <sec:intercept-url pattern="/protected/**" />      <sec:custom-filter ref="resourceServerFilter"     before="PRE_AUTH_FILTER" />     <sec:access-denied-handler ref="oauthAccessDeniedHandler" /> </sec:http>  <bean id="oauthAuthenticationEntryPoint"     class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"> </bean>  <bean id="clientAuthenticationEntryPoint"     class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">     <property name="realmName" value="springsec/client" />     <property name="typeName" value="Basic" /> </bean>  <bean id="oauthAccessDeniedHandler"     class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"> </bean>  <bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">     <property name="authenticationManager" ref="authenticationManager" /> </bean>  <sec:authentication-manager alias="authenticationManager">     <sec:authentication-provider     user-service-ref="clientDetailsUserService">     </sec:authentication-provider> </sec:authentication-manager>  <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">     <constructor-arg ref="clientDetails" /> </bean>  <bean id="clientDetails"     class="com.sample.context.security.InMemoryClientDetailsServiceSample"> </bean>    <oauth:authorization-server     client-details-service-ref="clientDetails" token-services-ref="tokenServices">     <oauth:password authentication-manager-ref="authenticationManager" /> </oauth:authorization-server>   <oauth:resource-server id="resourceServerFilter" token-services-ref="tokenServices" />  <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JwtTokenStore">     <constructor-arg ref="JwttokenConverter"></constructor-arg> </bean>  <bean id="JwttokenConverter"     class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter" />     <bean id="tokenServices" class="com.sample.context.security.JWTokenServices">     <property name="tokenStore" ref="tokenStore" />     <property name="supportRefreshToken" value="false" />     <property name="accessTokenValiditySeconds" value="3600"></property>     <property name="clientDetailsService" ref="clientDetails" />     <property name="accessTokenEnhancer" ref="JwttokenConverter"></property> </bean>    </beans> 

It seem resourceServerFilter is not used during testgetProtectedResource().

Thank for reading me :).

回答1:

There appears to be a few issues that are apparent to me.

Use springSecurityFilterChain

Instead of using resourceServerFilter, you should use springSecurityFilterChain which contains the authorization rules.

Map the Security Filter to "/**"

The mapping for MockMvc's Filter is mapped only to /protected, but it should be mapped to every URL. Internally Spring Security will only invoke the necessary Filters.

A summary of the two changes can be found below:

MockMvc mockMvc;  // use springSecurityFilterChain @Autowired private Filter springSecurityFilterChain;  @Before public void setup() {     mockMvc = MockMvcBuilders        .webAppContextSetup(context)        // Use springSecurityFilterChain & remove "/protected"        .addFilter(springSecurityFilterChain)        .build(); } 

Missing intercept-url@access

The configuration is missing the intercept-url@access attribute. For example

<sec:http pattern="/protected/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint">     <sec:anonymous enabled="false" />      <!-- Ensure you define an access attribute below! -->     <sec:intercept-url pattern="/protected/**" access="ROLE_USER"/>      <sec:custom-filter ref="resourceServerFilter"     before="PRE_AUTH_FILTER" />     <sec:access-denied-handler ref="oauthAccessDeniedHandler" /> </sec:http> 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!