【问题标题】:How to handle HTTP OPTIONS requests in Spring Boot?如何在 Spring Boot 中处理 HTTP OPTIONS 请求?
【发布时间】:2016-01-24 16:25:22
【问题描述】:

首先,我读过“How to handle HTTP OPTIONS with Spring MVC?”,但答案似乎并不直接适用于 Spring Boot。

看来我应该这样做:

通过设置 dispatcherServlet 来配置 dispatchOptionsRequesttrue

但是如何做到这一点,因为我的代码中没有 XML 配置或任何类型的 DispatcherServlet 初始化器类 (mentioned by this answer)?

@RestController 类中,我有一个这样的方法,目前没有被调用。

@RequestMapping(value = "/foo", method = RequestMethod.OPTIONS)
public ResponseEntity options(HttpServletResponse response) {
    log.info("OPTIONS /foo called");
    response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS");
    return new ResponseEntity(HttpStatus.OK);
}

Spring Boot 1.2.7.RELEASE;一个简单的设置,与Spring REST guide 中的设置没有太大区别。

【问题讨论】:

  • 在我的回答中添加了解决此问题的其他方法。还提交了PR 以允许以更多“Spring Boot 方式”(通过属性)进行配置。

标签: spring spring-mvc spring-boot http-options-method


【解决方案1】:

选项 1:Spring Boot 属性(仅限 Spring Boot 1.3.0+)

从 Spring Boot 1.3.0 开始,可以使用以下属性配置此行为:

spring.mvc.dispatch-options-request=true

选项 2:自定义DispatcherServlet

Spring Boot 中的DispatcherServletDispatcherServletAutoConfiguration 定义。您可以在配置类中的某处创建自己的 DispatcherServlet bean,它将用于代替自动配置中的那个:

@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(true);
    return dispatcherServlet;
}

但请注意,定义 DispatcherServlet bean 将禁用自动配置,因此您应该手动定义在自动配置类中声明的其他 bean,即 ServletRegistrationBeanDispatcherServlet

选项 3:BeanPostProcessor

您可以创建BeanPostProcessor 实现,它将在初始化bean 之前将dispatchOptionsRequest 属性设置为true。 Yoy 可以把它放在你的配置类中:

@Bean
public DispatcherServletBeanPostProcessor dispatcherServletBeanPostProcessor() {
    return new DispatcherServletBeanPostProcessor();
}

public static class DispatcherServletBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DispatcherServlet) {
            ((DispatcherServlet) bean).setDispatchOptionsRequest(true);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

选项 4:SpringBootServletInitializer

如果您的应用程序中有 SpringBootServletInitializer,您可以执行以下操作来启用 OPTIONS 调度:

public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        servletContext.getServletRegistration(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
                .setInitParameter("dispatchOptionsRequest", "true");
    }
}

这只有在您将应用程序作为 WAR 部署到 Servlet 容器中时才有效,因为在使用 main 方法运行 Spring Boot 应用程序时不会执行 SpringBootServletInitializer 代码。

【讨论】:

  • 重要更新:从 Spring Framework 4.3 开始将默认支持 OPTIONS 请求(默认用于即将发布的 Spring Boot 1.4 版本),请参阅jira.spring.io/browse/SPR-13130 了解更多详细信息。
【解决方案2】:

我在使用基于 Spring Boot 1.3.x 的 rest 应用程序时遇到了这个问题,在诊断问题时,我允许我的 Spring Tool Suite 更新到最新版本。

当我在更新的 STS 中创建一个新的测试 Spring Boot RestController 时,它的工作原理与 Spring 4.3 下的文档广告一样。我注意到新测试应用程序中的 Maven 依赖项已跳转到 spring boot 1.5.8,所以我只是将旧应用程序的依赖项更改为 spring boot 1.5.8 / spring 4.3.12。这解决了这个问题,现在它正在使用 RequestMapping 注释指定处理 OPTIONS 请求的兴趣...

@RequestMapping(value="/account/{id}", method={RequestMethod.OPTIONS,RequestMethod.GET})

...现在将 OPTIONS 请求发送到处理程序。

因此,如果您能够更新到更高版本的 Spring,则无需定义任何特殊配置即可启用 OPTIONS 请求方法处理(Spring 4.3.12 / Spring Boot 1.5.8)。

【讨论】:

  • 我想这通常不是我们想要的。 OPTIONS 请求通常是 CORS 飞行前请求,它们的工作方式不应与“真实”请求相同。
  • 我同意。使用控制器处理 OPTIONS 并不是我实际上最终要做的事情,因为更高版本的 Spring 通过 Crossorigin 注释自动处理预检请求,这通常是人们想要的。让处理程序处理 OPTIONS 只是最终使用 Crossorigin 注释的一步。附带说明一下,如果您正在为 OPTIONS 方法编写测试并想知道为什么没有返回 CORS 标头,则必须设置一些请求标头才能发生这种情况,最低限度是 Origin 和 access-control-request-method。跨度>
【解决方案3】:

您可以使用 Spring Boot 2.2.6 轻松地将自定义方法 OPTIONS 添加到 StrictHttpFirewall

@Bean
public StrictHttpFirewall httpFirewall() {

    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowedHttpMethods(Arrays.asList("GET", "POST", "OPTIONS", "FOO"));

    return firewall;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 2019-05-27
    • 2013-02-02
    • 2013-04-13
    • 2010-09-18
    • 2012-03-20
    相关资源
    最近更新 更多