资源服务器测试因 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 中。与 RouterFunctions 结合使用时,MockMvcMVC_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 看看有没有什么可以做到。