tomcat启用options请求

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tomcat启用options请求相关的知识,希望对你有一定的参考价值。

参考技术A 1. 设置Tomcat / server.xml文件 connectiontimeout 值,默认为20000ms,修改为8000ms(Tomcat 自身安全漏洞) (如果还是不行,再改小一点)
2. 设置AJAX的全局timeout时间(默认为30000ms) $.ajaxSetup(timeout:8000);
3. If possible, you should set the Secure flag for this

使用 Spring Framework 为 OPTIONS 请求启用 CORS

【中文标题】使用 Spring Framework 为 OPTIONS 请求启用 CORS【英文标题】:Enable CORS for OPTIONS request using Spring Framework 【发布时间】:2016-10-10 13:14:23 【问题描述】:

每次我对我的服务进行 PUT Ajax 调用时,它都会返回以下错误:

XMLHttpRequest 无法加载 http://localhost:8080/users/edit。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost:63342' 不允许访问。响应的 HTTP 状态代码为 403。

经过 2 天的调查,我已经尝试在我的代码上尝试下一个解决方案。

这是我加载必要的类并运行应用程序的主类

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(DispatcherServletInitializer.class, OptionsController.class,Application.class);
    

DispatcherServilet 初始化程序,我在其中启用了 dispatchOptionsRequest:

public abstract class DispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer 

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) 
        registration.setInitParameter("dispatchOptionsRequest", "true");
        super.customizeRegistration(registration);
    

用于处理所有 OPTIONS 请求的 控制器

@Controller
public class OptionsController 

    @RequestMapping(method = RequestMethod.OPTIONS)
    public HttpServletResponse handle(HttpServletResponse theHttpServletResponse) throws IOException 
        theHttpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with");
        theHttpServletResponse.addHeader("Access-Control-Max-Age", "60"); 
        theHttpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        theHttpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
        return theHttpServletResponse;
    


我做错了什么配置?

【问题讨论】:

您在控制器spring.io/guides/gs/rest-service-cors 中尝试过@CrossOrigin 吗? (我认为它是在启动 1.3.0 中添加的) 刚刚将@CrossOrigin(origins = "*", maxAge = 3600) 行添加到控制器,仍然是同样的错误。 您是否在测试时禁用了选项控制器?仅该注释就可以完成所有工作 你终于说对了! =) 将方法@RequestMapping( value = "/**", method = RequestMethod.OPTIONS ) public ResponseEntity handle() return new ResponseEntity(HttpStatus.OK); 添加到我的控制器解决了它!谢谢! @daniegarcia254 为什么不添加解决问题的代码?这将有助于未来的读者。 【参考方案1】:

最后,DispatcheServlet 自定义初始化程序是真正解决了我的问题的类。 OPTIONS 请求失败,因为我实现了 optionsController,这是错误的。

所以我删除了那个 optionsController,并且仅仅通过在我的 Rest Controller 中为 OPTIONS 请求添加 handle 方法,问题就解决了:

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/users")
public class Users 

    @RequestMapping(
            value = "/edit",
            method = RequestMethod.PUT)
    public ResponseEntity<?> create(@RequestBody User user)
         ....
         ....
    

    @RequestMapping(
            value = "/**",
            method = RequestMethod.OPTIONS
    )
    public ResponseEntity handle() 
        return new ResponseEntity(HttpStatus.OK);
    

【讨论】:

【参考方案2】:

如果您使用现代版本的 Spring (4.2),您可以受益于 @CrossOrigin。 事实上,如果您使用 Spring

package it.valeriovaudi.web.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 Copyright 2015 Valerio Vaudi
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
public class CORSFilter implements Filter 
    public static final String ACCESS_CONTROL_ALLOW_ORIGIN_NAME = "Access-Control-Allow-Origin";
    public static final String DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE = "*";

    public static final String ACCESS_CONTROL_ALLOW_METHDOS_NAME = "Access-Control-Allow-Methods";
    public static final String DEFAULT_ACCESS_CONTROL_ALLOW_METHDOS_VALUE = "POST, GET, OPTIONS, DELETE";

    public static final String ACCESS_CONTROL_MAX_AGE_NAME = "Access-Control-Max-Age";
    public static final String DEFAULT_ACCESS_CONTROL_MAX_AGE_VALUE = "3600";

    public static final String ACCESS_CONTROL_ALLOW_HEADERS_NAME = "Access-Control-Allow-Headers";
    public static final String DEFAULT_ACCESS_CONTROL_ALLOW_HEADERS_VALUE = "x-requested-with";

    private String accessControlAllowOrigin = DEFAULT_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE;
    private String accessControlAllowMethods = DEFAULT_ACCESS_CONTROL_ALLOW_METHDOS_VALUE;
    private String accessControlAllowMaxAge = DEFAULT_ACCESS_CONTROL_MAX_AGE_VALUE;
    private String accessControlAllowHeaders = DEFAULT_ACCESS_CONTROL_ALLOW_HEADERS_VALUE;

    /**
     * @return the method return a map that associated the name of paramiters in the web.xml to the class variable name for the header binding*/
    private Map<String,String> initConfig()
        Map<String, String> result = new HashMap<>();

        result.put(ACCESS_CONTROL_ALLOW_ORIGIN_NAME,"accessControlAllowOrigin");
        result.put(ACCESS_CONTROL_ALLOW_METHDOS_NAME,"accessControlAllowMethods");
        result.put(ACCESS_CONTROL_MAX_AGE_NAME,"accessControlAllowMaxAge");
        result.put(ACCESS_CONTROL_ALLOW_HEADERS_NAME,"accessControlAllowHeaders");

        return result;
    

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        String initParameterValue;
        Map<String, String> stringStringMap = initConfig();

        for (Map.Entry<String, String> stringStringEntry : stringStringMap.entrySet()) 
            initParameterValue = filterConfig.getInitParameter(stringStringEntry.getKey());

            // if the init paramiter value isn't null then set the value in the correct http header
            if(initParameterValue!=null)
                try 
                    getClass().getDeclaredField(stringStringEntry.getValue()).set(this, initParameterValue);
                 catch (IllegalAccessException | NoSuchFieldException ignored)  
            
        
    

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException 
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_NAME, accessControlAllowOrigin);
        response.setHeader(ACCESS_CONTROL_ALLOW_METHDOS_NAME, accessControlAllowMethods);
        response.setHeader(ACCESS_CONTROL_MAX_AGE_NAME, accessControlAllowMaxAge);
        response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_NAME, accessControlAllowHeaders);

        filterChain.doFilter(servletRequest, servletResponse);
    

    @Override
    public void destroy() 
    


在 Spring Boot 中,您可以将此过滤器注册为 Spring Bean,Spring 将为您注册过滤器。

希望对你有帮助。

【讨论】:

你如何使用@CrossOrigin ?

以上是关于tomcat启用options请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Framework 为 OPTIONS 请求启用 CORS

Tomcat Jersey 在“OPTIONS”飞行前请求中阻止服务器

Tomcat 8 未响应来自 CriOS 的 OPTIONS 请求

Yii 和 Vue2 CORS 启用。服务器以 404 错误响应预检 OPTIONS 请求

Preflight(options) 请求的正确成功状态代码是啥? [复制]

使用 EnableCors 时“请求的资源不支持 http 方法 'OPTIONS'”