【问题标题】:CORS in spring boot is not working - getting empty response弹簧靴中的 CORS 不起作用 - 得到空响应
【发布时间】:2020-04-20 15:57:44
【问题描述】:

我将 Spring Boot (Tomcat + Java) 用于我的后端应用程序,并将 React 用于我的前端。 我正在尝试从“http://localhost:3000”访问“http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03”。

我在控制器级别和端点级别都添加了@CrossOrigin(origins = "*")。我得到空的结果。 我在控制器级别和端点级别都添加了@CrossOrigin。结果是空的。

如果我删除 @CrossOrigin 注释,我会收到 Cors 错误。这意味着注释是必要的。错误是“访问从源'http://localhost:3000'获取'http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03'已被CORS策略阻止:请求的资源上不存在'Access-Control-Allow-Origin'标头。如果提供不透明的响应根据您的需要,将请求的模式设置为 'no-cors' 以获取禁用 CORS 的资源。”

如果我直接将链接复制粘贴到浏览器中,它可以正常工作并返回 JSON。 如果我调用“https://cdn.rawgit.com/rrag/react-stockcharts/master/docs/data/MSFT.tsv”,它也会返回结果。

为避免拼写错误,我使用了 console.log,并从 console.log 中粘贴了这些内容。

我正在使用 fetch 进行“获取”。

[编辑 1] 我正在查看 tomcat 日志,很快就会更新。

[编辑 2] TL;博士 这不是 CORS 问题。

完整说明: 1.“http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03”的响应是200。

  1. 我登录了 spring boot 应用并查看了 tomcat 日志。它达到了控制器方法,我从数据库中得到了正确的结果。当我发回响应时,我在浏览器中得到空结果。如前所述,如果我直接点击 url,我会得到正确的结果。

  2. 这不是预检 OPTIONS 请求。

  3. 所以可以断定不是CORS问题。 @CrossOrigin 注释有效

我在发布问题后查看了日志。所以这个问题可以关闭,因为它是不正确的。如果我无法解决空响应问题,我将发布一个单独的问题,因为这个问题的标题具有误导性。

谢谢大家的回复。

【问题讨论】:

  • 请使用stackoverflow.com/q/59555658/441757 编辑/更新问题并粘贴您用于发送请求和检查响应的确切前端 JavaScript 代码的 sn-p。
  • 响应的 HTTP 状态码是什么?您可以使用浏览器开发工具中的网络窗格进行检查。是 4xx 还是 5xx 错误而不是 200 OK 成功响应?它是对 CORS preflight OPTIONS 请求的响应吗?

标签: java spring spring-boot cors


【解决方案1】:

我以这种方式使用它来允许来自所有来源的请求。它适用于我的所有项目。

package com.example.demo.filters;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class CORSFilter extends OncePerRequestFilter {

    @Override
    public void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
            final FilterChain filterChain) throws ServletException, IOException {

        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
                "Origin, Content-Type, Accept, Authorization, Accept-Language, connection, Cache-Control, Access-Control-Request-Method, Access-Control-Request-Headers");
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD");
        response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS,
                "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeader(HttpHeaders.ORIGIN));
        filterChain.doFilter(request, response);

    }
}

【讨论】:

  • 我没有尝试这个选项,因为 @CrossOrigin 注释本身正在工作。请参阅我的编辑 2。
【解决方案2】:

我只在应用程序级别配置过 CORS, 但是@CrossOrigin 注释的documentation 表示默认情况下它允许所有来源,因此您可能想尝试 @CrossOrigin() 代替 @CrossOrigin(origins = "*")

文档还说它支持“@RequestMapping 注解中指定的 HTTP 方法”,因此您可能需要在 GET 或 POST 或您当前使用的任何方法之外添加 OPTIONS 方法(CORS 需要支持OPTIONS 方法)。

【讨论】:

  • @CrossOrigin() 和@CrossOrigin 一样,我试过了。请参阅我的编辑 2。它正在工作,我在观察日志后意识到了这一点。
【解决方案3】:

您可以在您的 api 端点中使用 @CrossOrigin 而无需提及来源。

指定来源也可能对多层环境造成影响。

【讨论】:

    【解决方案4】:

    请记住,Access-Control-Allow-Origin: * 仅在您没有任何身份验证方法(没有凭据的请求)时使用。见:

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

    如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源

    不要在 fetch 调用中使用 'no-cors',因为您会得到 不透明 响应。要么指定'cors',要么不指定任何内容。

    const response = await fetch("http://localhost:8080", {
       method: 'GET',
       // mode: 'cors',
       headers: {
          'Accept': 'application/json'
       }
    });
    

    实际上,当您收到 200 OKopaque 响应时,服务器不再有问题。响应为 200,但数据不透明,因为前端可能设置了“no-cors”或类似设置。见:

    https://developers.google.com/web/updates/2015/03/introduction-to-fetch

    关于后端,在 Spring Boot(w/Kotlin)中,我使用它来发送 Access-Control-Allow-Origin: * 标头,基于 spring-boot-starter-security 库。

    package demo.config
    
    import org.springframework.context.annotation.Configuration
    import org.springframework.security.config.annotation.web.builders.HttpSecurity
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
    
    @Configuration
    class GeneralApiSecurityConfig() : WebSecurityConfigurerAdapter() {
        override fun configure(http: HttpSecurity) {
            http.cors()
        }
    }
    

    只要http.cors()

    哦,这可能是一条微不足道的建议,但是如果您弄乱了配置,请每次重新启动服务器,否则,您可能正在刷新前端客户端,但服务器正在坚持以前的尝试。

    【讨论】:

      猜你喜欢
      • 2021-09-17
      • 2018-07-10
      • 2016-10-21
      • 1970-01-01
      • 2018-09-16
      • 2017-04-29
      • 2017-11-14
      • 2022-07-18
      • 1970-01-01
      相关资源
      最近更新 更多