弹簧靴中的 CORS 不起作用 - 得到空响应

Posted

技术标签:

【中文标题】弹簧靴中的 CORS 不起作用 - 得到空响应【英文标题】:CORS in spring boot is not working - getting empty response 【发布时间】: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。

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

    这不是预检 OPTIONS 请求。

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

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

谢谢大家的回复。

【问题讨论】:

请使用***.com/q/59555658/441757 编辑/更新问题并粘贴您用于发送请求和检查响应的确切前端 javascript 代码的 sn-p。 响应的 HTTP 状态码是什么?您可以使用浏览器开发工具中的网络窗格进行检查。是 4xx 还是 5xx 错误而不是 200 OK 成功响应?它是对 CORS preflight OPTIONS 请求的响应吗? 类似于***.com/questions/56759527/… 【参考方案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()

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

【讨论】:

以上是关于弹簧靴中的 CORS 不起作用 - 得到空响应的主要内容,如果未能解决你的问题,请参考以下文章

弹簧靴。 CORS。 'allowCredentials = false' 不起作用

用于弹簧靴的 CORS 过滤器不起作用

CORS XHR 重定向不起作用

如何隐藏“孩子”:[]从弹簧靴中一对多关系中的最后一个孩子

为啥弹簧测试失败,不起作用@MockBean

使用Java Config的全局CORS配置不起作用