【问题标题】:Spring Restful: Handling OPTIONS requestSpring Restful:处理 OPTIONS 请求
【发布时间】:2018-01-03 00:02:50
【问题描述】:

我们正在使用 Spring Restful、oAuth、MVC 服务器端,如果服务器和 Web 应用程序在同一台服务器上运行,它可以正常工作。

我们在不同的域中运行服务器和 Web 应用程序,我们面临无效会话错误。

当我们发出呼叫后浏览器发出 OPTIONS 请求时,立即发出呼叫失败。

我们启用了 CORS 过滤器,因此 OPTIONS 调用返回 200,但它使当前会话无效,因此下一个 post 调用失败。

我们没有发送 OPTIONs 请求,所以它直到拦截器仍然无效会话才到达。

我们尝试了以下解决方案:

  • 分派 OPTIONS 请求并在拦截器中处理它。它创建新会话但无法存储它的持久性。所以还是失败了
  • 在查询参数中发送自定义访问令牌标头和会话 Cookie,但我们无法在 JavaScript 中访问会话 cookie。

我试图避免在 OPTIONS 请求上创建新会话,请告诉我们如何在 Spring 或 Tomcat 中避免。

我们还需要为混合移动应用程序支持此解决方案(因为它不支持 cookie)。

启用 CORS:

在 web.xml 中:

<filter>
    <filter-name>CORSFilter</filter-name>
    <filter-class>com.tip.uiux.service.framework.CORSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

在 CORSFilter.java 中

@Override
public void doFilter(ServletRequest req, ServletResponse res,
          FilterChain chain) throws IOException, ServletException {
         HttpServletResponse response = (HttpServletResponse) res;
         response.setHeader("Access-Control-Allow-Origin", "*");
         response.setHeader("Access-Control-Allow-Credentials", "true");
         response.setHeader("X-Frame-Options", "DENY");
         response.setHeader("Access-Control-Allow-Methods","POST, GET, HEAD, OPTIONS");
         response.setHeader("Access-Control-Allow-Headers",
           "Custom-Access-Token, Origin, Accept, Session-Alias, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
         //LOGGER.info("Request Filtered for Cross Origin Resource Sharing using CORSFilter with custom headers");
         chain.doFilter(req, res); 
}

【问题讨论】:

  • 向我们展示您是如何启用 CORS 的。
  • @StanislavL,我们已经更新了这个问题。我们启用了 cors,这就是为什么它为 OPTIONS 请求返回 200
  • 只有在调用选项时才会失败,否则它工作正常。

标签: java spring spring-mvc tomcat7 spring-rest


【解决方案1】:

您还应该在响应中添加相关标头。请在您的应用程序中使用以下 CORS 过滤器。

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
    @Autowired
    Environment environment;

    public CorsFilter() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;

        HttpServletRequest request = (HttpServletRequest) req;

        if (Arrays.stream(this.environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("development")))) {
            response.setHeader("Access-Control-Allow-Origin", "http://dev.yourdomain.com");
        } else if (Arrays.stream(this.environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("production")))) {
            response.setHeader("Access-Control-Allow-Origin", "https://www.yourdomain.com");
        } else {
            response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
        }


        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, Authorization, X-Requested-With, Content-Type, Accept, Key");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

请注意,过滤器还会在标题中添加一些域信息(对于开发和生产环境,默认为 localhost)。如果您想使用它们,您可以为这些部分提供自己的域。

希望对你有帮助

【讨论】:

  • 我们已经尝试过了,我们已经编辑了问题,请检查一次。
  • 它没有到达拦截器,但它仍然使当前会话无效。
  • @NarendraKurapati 好的,对不起。当我写答案时,它没有更新的部分,所以我没有看到它。
  • 也可以动态设置原点:response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
猜你喜欢
  • 2016-01-24
  • 2016-07-27
  • 2010-09-18
  • 2021-03-23
  • 1970-01-01
  • 2012-06-19
  • 2015-08-12
  • 2013-02-02
  • 2021-09-26
相关资源
最近更新 更多