[spring-projects/spring-boot]自动配置 HandlerInterceptor 无法在演示项目中看到

2024-07-08 576 views
2

项目:https://github.com/orubel/spring-boot-starter-beapi

一直尝试在自动配置中配置 handlerInterceptor 一段时间,现在可用。

每次我拨打电话时,我总是在演示项目中看到相同的内容:

12:31:35.712 [http-nio-8080-exec-1] DEBUG i.b.a.f.RequestInitializationFilter - doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) : {}
12:31:35.762 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - GET "/v0.4-1/user/show/5", parameters={}
12:31:35.768 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to demo.application.controller.UserController#show(HttpServletRequest, HttpServletResponse)
12:31:35.784 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - 
 ...
12:31:35.803 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
12:31:35.804 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Writing [{user=demo.application.domain.User@76aca0ae}]
12:31:35.861 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Completed 200 OK

调用工作正常,但我需要 handlerInterceptor 来处理 FORWARD,这样一旦预处理完成,handlerInterceptor 就可以使用 preHandle/postHandle 处理所有路由

在阅读这篇文章(https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/handler-interceptors-registration.html)时,看起来好像我需要设置一个 HandlerMapping,但是当按照前面的例子中的示例时,我仍然一无所获......

这是一个错误吗?

回答

8

哦,这是我目前正在使用但尚未提交的代码:


    @Bean
    public ApiInterceptor apiInterceptor() {
        return new ApiInterceptor(principle(), apiCacheService(), apiProperties);
    }

    //@Bean
    //public BatchInterceptor batchInterceptor() {
    //  return new BatchInterceptor(principle(), apiCacheService(), apiProperties);
    //}

    //@Bean
    //public ChainInterceptor chainInterceptor() {
    //  return new ChainInterceptor(principle(), apiCacheService(), apiProperties);
    //}

    @Configuration
    public class BeapiWebAutoConfiguration implements WebMvcConfigurer {

/*
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();

            //List<RequestBodyAdvice> requestBodyAdvices = new ArrayList<>();
            //requestBodyAdvices.add(new BeapiRequestBodyAdvice(principle(),apiCacheService()))
            //requestMappingHandlerAdapter.setRequestBodyAdvice(requestBodyAdvices);

            List<ResponseBodyAdvice<?>> responseBodyAdvices = new ArrayList<>();
            responseBodyAdvices.add(new BeapiResponseBodyAdvice(principle(),apiCacheService()))
            requestMappingHandlerAdapter.setResponseBodyAdvice(responseBodyAdvices);

            return requestMappingHandlerAdapter;
        }
*/

        @Bean
        public SimpleUrlHandlerMapping simpleUrlHandlerMapping () {
            SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
            Map<String, Object> map = new HashMap<>();
            map.put("/app", httpRequestHandler());
            mapping.setUrlMap(map);
            mapping.setInterceptor(apiInterceptor()).addPathPatterns("/**");
            //mapping.setInterceptors(new Object[]{new MyInterceptor()});
            return mapping;
        }

        @Bean
        BeapiHttpRequestHandler httpRequestHandler() {
            return new BeapiHttpRequestHandler();
        }

    }
1

您似乎没有向您的自定义添加任何拦截器RequestMappingHandlerAdapter,并且您的自定义SimpleUrlHandlerMapping没有用于日志中的请求。

如果我遗漏了什么而您认为这里有一个错误,请提供一个完整但最小的可重现该错误的示例,然后我们可以再看一下。

7

哦。我应该在“requestMappingHandlerAdapter”中执行此操作吗?我会尝试一下。

我给出的例子表明使用 simpleUrlAdapter

正在使用 requestMappingHandlerAdapter 进行建议(我暂时将其注释掉)。

9

不,同样的事情。

14:37:59.047 [http-nio-8080-exec-1] DEBUG i.b.a.f.RequestInitializationFilter - doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) : {}
14:37:59.091 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - GET "/v0.4-1/user/show/5", parameters={}
14:37:59.097 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to demo.application.controller.UserController#show(HttpServletRequest, HttpServletResponse)
14:37:59.112 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - 
 ...
14:37:59.128 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
14:37:59.138 [http-nio-8080-exec-1] DEBUG i.b.api.interceptor.ApiInterceptor - (BeapiResponseBodyAdvice) beforeBodyWrite(Object, MethodParameter, MediaType, Class, ServletHttpRequest, ServletHttpResponse) - parses RESPONSE output against expect output for ROLE for endpoint (see https://apisecurity.io/encyclopedia/content/owasp/api3-excessive-data-exposure.htm)
14:37:59.186 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Writing [{id=5, username=admin, accountExpired=null, version=0, enabled=true, email=orubel@gmail.com}]
14:37:59.222 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Completed 200 OK

这是新功能...

        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();

            requestMappingHandlerAdapter.setInterceptor(apiInterceptor()).addPathPatterns("/**");

            //List<RequestBodyAdvice> requestBodyAdvices = new ArrayList<>();
            //requestBodyAdvices.add(new BeapiRequestBodyAdvice(principle(),apiCacheService()))
            //requestMappingHandlerAdapter.setRequestBodyAdvice(requestBodyAdvices);

            List<ResponseBodyAdvice<?>> responseBodyAdvices = new ArrayList<>();
            responseBodyAdvices.add(new BeapiResponseBodyAdvice(principle(),apiCacheService()))
            requestMappingHandlerAdapter.setResponseBodyAdvice(responseBodyAdvices);

            return requestMappingHandlerAdapter;
        }

/*
        @Bean
        public SimpleUrlHandlerMapping simpleUrlHandlerMapping () {
            SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
            Map<String, Object> map = new HashMap<>();
            map.put("/app", httpRequestHandler());
            mapping.setUrlMap(map);
            mapping.setInterceptor(apiInterceptor()).addPathPatterns("/**");
            //mapping.setInterceptors(new Object[]{new MyInterceptor()});
            return mapping;
        }

        @Bean
        BeapiHttpRequestHandler httpRequestHandler() {
            return new BeapiHttpRequestHandler();
        }
*/
1

记录一下,preHandle/postHandle 处有一个 DEBUG 语句,所以我需要看到它们才能知道拦截器是否正常工作。

我看到了建议(并且我知道它正在处理主体),所以我知道建议工作正常,但拦截器从未被调用

8

谢谢。不幸的是,这不是我真正想要的。恐怕我没有时间从粘贴在这里的代码片段和您的启动器链接中拼凑出一些东西。如果您希望我们花更多时间调查,请花一些时间提供一个完整但最小的样本。该示例应该是独立的,并且尽可能让我们轻松运行它并重现问题。您可以通过将其推送到 GitHub 上的单独存储库或将其压缩并附加到此问题来与我们分享。

4

就行了。我会删除不必要的部分并创建一个简单的示例。甚至可能解决我的问题。呵呵

今天下午就交给你。:)

9

我的潜在问题似乎是 FILTER、INTERCEPTOR 和 ADVICE 应该能够协同工作,而且它们确实在项目中协同工作了……但是当尝试将它们从自动配置推送到演示项目时,它们会选择性地工作或存在集成问题。所以不管怎样,我都必须为您提供自动配置和演示项目……但我可以消除一些麻烦。

  • 我可以不使用过滤器,但我需要拦截器进行路由;可以将功能从过滤器移动到拦截器
  • 我还需要 ResponseBodyAdvice 来解析实体(以确保缓存的对象为端点的角色返回正确的数据)请参阅 OWASP - API3:2019 过度数据暴露

我认为现在这个问题可能特定于“自动配置”,所以无论我构建什么都必须有一个自动配置和一个演示项目来展示这一点。

3

这完全没问题。理想情况下,示例应该尽可能简单,以便重现问题,但不能太简单。

4

好的。我只是删除了一些多余的、未使用的文件和功能,所以你只需要关注正在发生的事情。

还没有测试引导用户,但是我在数据库中检查过它并且它在那里,所以应该没问题。

为了确保万无一失,明天早上将进行更多测试,但一些基本测试表明它运行良好。

https://github.com/orubel/beapi-spring-boot-test/

有一些关于构建/配置的基本说明...如果您有任何问题请告诉我,我会立即赶到。

7

谢谢,但恐怕这仍然不是我想要的,因为它看起来不够简单。例如,重现与 Web 相关的问题不需要数据库。如果需要任何与 JWT 相关的代码,我也会感到惊讶。

无论如何,我花了一些时间尝试使用 MySQL 5.7.36 和 Java 1.8 运行它,但由于 SSL 握手失败而无法连接。此时,我注意到您正在使用 Spring Boot 2.2,自 2020 年 10 月 16 日起不再支持 OSS。我还注意到您正在将演示应用程序配置为自动配置中的组件扫描类。这将导致它们被视为应用程序配置的一部分,而不是自动配置。

如果您希望我们花更多时间处理这个问题,请提供一个真正能重现问题的最小示例。从头开始并逐步构建直到问题发生可能比重新剥离已有内容更容易。此外,除非问题特定于 Groovy,否则最好使用 Java 编写示例,因为它可以消除一个可能的原因。

6

因此问题并不只存在于 Groovy(我知道会出现这种情况),因为它已在本地 Springboot 项目以及带有 Springboot 的 Grails 插件中使用。拦截器在本地项目中运行良好

但升级肯定有帮助:)

我可以在没有 JWT 或 DB 的情况下再试一次并升级项目。

交接前也会进行更好的测试。抱歉。

2

你知道。我高度怀疑你用“ComponentScan”搞定了这个问题;我完全忘记了它的存在,也不知道它在执行此操作时会忽略自动配置。

将运行更多测试(并构建更多测试)并进行更多配置,但我认为你已经成功了。

请关闭,因为我不想再浪费任何人的时间,如果能解决问题,我只会在这里编辑并附上注释:)

再次感谢。

1

好的,所以 ComponentScan 是正确的,因为 Filter/Interceptor/Advice 需要在项目中,因为请求/响应流经项目(而不是自动配置);所以这实际上是将它们引入……但不是正确的方法。所以你肯定为我指明了更好的方向

再次感谢。 :)