资源服务器测试因 Auth0 颁发者 uri 而失败
Resource server test fails with Auth0 issuer uri
我创建了一个简单的例子,只作为资源服务器为客户端提供API。
完整的代码可以在Github - hantsy/spring-webmvc-auth0-sample上找到。
我浏览过 Spring security samples,它使用了 jwk-set-uri
,在我的应用程序中,我使用了 issuer-uri
。
security:
oauth2:
resourceserver:
jwt:
issuer-uri: <auth0 provided issuer uri>
然后我关注 Auth0 Spring security 5 API Guide ,添加观众声明验证。
我尝试使用 MockMVC 添加 ApplicationTests。
@Test
public void testGetById() throws Exception {
Post post = Post.builder().title("test").content("test content").build();
post.setId(1L);
given(this.posts.findById(anyLong())).willReturn(Optional.of(post));
this.mockMvc
.perform(
get("/posts/{id}", 1L)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("test"));
verify(this.posts, times(1)).findById(any(Long.class));
verifyNoMoreInteractions(this.posts);
}
我的安全配置与此类似。
@Bean
SecurityFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
return http
.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeRequests(c -> c
.antMatchers("/", "/info").permitAll()
.antMatchers(HttpMethod.GET, "/posts/**").permitAll()//.hasAuthority("SCOPE_read:posts")
.antMatchers(HttpMethod.POST, "/posts/**").hasAuthority("SCOPE_write:posts")
.antMatchers(HttpMethod.PUT, "/posts/**").hasAuthority("SCOPE_write:posts")
.antMatchers(HttpMethod.DELETE, "/posts/**").hasAuthority("SCOPE_delete:posts")
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.cors().and().build();
}
当运行测试时。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.test.web.servlet.DefaultMvcResult.setHandler(Object)" because "mvcResult" is null
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
不知道哪里错了?我检查了官方样本,它包含一个 spring.factories file 来启用模拟服务器环境,它在 Spring Boot?
中是必需的
问题似乎是在配置中包含 cors()
。
Spring 安全性的 CorsFilter
默认委托给 HandlerMappingInterceptor
,它将请求包装在专门的 HttpServletRequestWrapper
中。与 RouterFunction
s 结合使用时,MockMvc
的 MVC_REQUEST_ATTRIBUTE
请求属性将被删除。
然后,一个解决方法是从您的配置中删除 cors()
。事实上,当我从你的样本中删除它时,测试 运行 符合预期。
另一种是不使用 HandlerMappingInterceptor
默认值。相反,您可以发布自己的 CorsConfigurationSource
,如下所示:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
在您的示例应用程序中,当我将以上内容添加到您的 SecurityConfig
时,再次按预期进行测试 运行。
似乎有一种方法可以在 HandlerMappingIntrospector
中调整这个专门的包装器,以免意外删除 MVC_REQUEST_ATTRIBUTE
,但是 the Spring Framework team will probably have more to say if any adjustments are needed. I've filed a ticket 看看有没有什么可以做到。
我创建了一个简单的例子,只作为资源服务器为客户端提供API。
完整的代码可以在Github - hantsy/spring-webmvc-auth0-sample上找到。
我浏览过 Spring security samples,它使用了 jwk-set-uri
,在我的应用程序中,我使用了 issuer-uri
。
security:
oauth2:
resourceserver:
jwt:
issuer-uri: <auth0 provided issuer uri>
然后我关注 Auth0 Spring security 5 API Guide ,添加观众声明验证。
我尝试使用 MockMVC 添加 ApplicationTests。
@Test
public void testGetById() throws Exception {
Post post = Post.builder().title("test").content("test content").build();
post.setId(1L);
given(this.posts.findById(anyLong())).willReturn(Optional.of(post));
this.mockMvc
.perform(
get("/posts/{id}", 1L)
.accept(MediaType.APPLICATION_JSON)
)
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("test"));
verify(this.posts, times(1)).findById(any(Long.class));
verifyNoMoreInteractions(this.posts);
}
我的安全配置与此类似。
@Bean
SecurityFilterChain springWebFilterChain(HttpSecurity http) throws Exception {
return http
.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeRequests(c -> c
.antMatchers("/", "/info").permitAll()
.antMatchers(HttpMethod.GET, "/posts/**").permitAll()//.hasAuthority("SCOPE_read:posts")
.antMatchers(HttpMethod.POST, "/posts/**").hasAuthority("SCOPE_write:posts")
.antMatchers(HttpMethod.PUT, "/posts/**").hasAuthority("SCOPE_write:posts")
.antMatchers(HttpMethod.DELETE, "/posts/**").hasAuthority("SCOPE_delete:posts")
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.cors().and().build();
}
当运行测试时。
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.test.web.servlet.DefaultMvcResult.setHandler(Object)" because "mvcResult" is null
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
不知道哪里错了?我检查了官方样本,它包含一个 spring.factories file 来启用模拟服务器环境,它在 Spring Boot?
中是必需的问题似乎是在配置中包含 cors()
。
Spring 安全性的 CorsFilter
默认委托给 HandlerMappingInterceptor
,它将请求包装在专门的 HttpServletRequestWrapper
中。与 RouterFunction
s 结合使用时,MockMvc
的 MVC_REQUEST_ATTRIBUTE
请求属性将被删除。
然后,一个解决方法是从您的配置中删除 cors()
。事实上,当我从你的样本中删除它时,测试 运行 符合预期。
另一种是不使用 HandlerMappingInterceptor
默认值。相反,您可以发布自己的 CorsConfigurationSource
,如下所示:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
在您的示例应用程序中,当我将以上内容添加到您的 SecurityConfig
时,再次按预期进行测试 运行。
似乎有一种方法可以在 HandlerMappingIntrospector
中调整这个专门的包装器,以免意外删除 MVC_REQUEST_ATTRIBUTE
,但是 the Spring Framework team will probably have more to say if any adjustments are needed. I've filed a ticket 看看有没有什么可以做到。