简体   繁体   English

春季启动中的 CORS 不起作用 - 得到空响应

[英]CORS in spring boot is not working - getting empty response

I am using Spring Boot (Tomcat + Java) for my backend app and React for my front end.我的后端应用程序使用 Spring Boot (Tomcat + Java),前端使用 React。 I am trying to access " http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 " from " http://localhost:3000 ".我试图从“ http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 ”访问“ http://localhost: 3000 ”。

I added @CrossOrigin(origins = "*") both at the controller level and at endpoint level.我在控制器级别和端点级别都添加了 @CrossOrigin(origins = "*") 。 I am getting empty result.我得到空结果。 I added @CrossOrigin both at the controller level and at endpoint level.我在控制器级别和端点级别都添加了@CrossOrigin。 I am getting empty result.我得到空结果。

If I remove the @CrossOrigin annotation, I am getting the Cors error.如果我删除 @CrossOrigin 注释,则会收到 Cors 错误。 That means the annotation is necessary.这意味着注释是必要的。 The error is "Access to fetch at ' http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 ' from origin ' http://localhost:3000 ' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."错误是“访问在 ' http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 ' from origin ' http: //localhost:3000 ' has been Blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the request resource. 如果不透明响应满足您的需求,请将请求的模式设置为 'no-cors' 以在禁用 CORS 的情况下获取资源。”

If I copy paste the link in the browser directly, it is working and returns JSON.如果我直接将链接复制粘贴到浏览器中,则它可以正常工作并返回 JSON。 If I call " https://cdn.rawgit.com/rrag/react-stockcharts/master/docs/data/MSFT.tsv " it is also returning result.如果我调用“ https://cdn.rawgit.com/rrag/react-stockcharts/master/docs/data/MSFT.tsv ”,它也会返回结果。

To avoid typos, I did console.log and I am pasting these from console.log.为了避免打字错误,我做了 console.log 并且我从 console.log 粘贴这些。

I am using fetch for 'get'ting.我正在使用 fetch 来获取 'get'ting。

[Edit 1] I am looking at the tomcat logs and will update it shortly. [编辑 1] 我正在查看 tomcat 日志并将很快对其进行更新。

[Edit 2] TL;DR It's not a CORS problem. [编辑 2] TL;DR 这不是 CORS 问题。

Full description: 1. The response for " http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 " was 200.完整说明: 1. “ http://localhost:8080/vr-backend-0.0.1-SNAPSHOT/stockdata/NIFTY19DECFUT?from=2019-12-03&to=2019-12-03 ”的响应为 200。

  1. I logged in the spring boot app and looked at the tomcat logs.我登录了 spring boot 应用程序并查看了 tomcat 日志。 It reaches the controller method and I get the proper results from DB.它到达控制器方法,我从 DB 得到正确的结果。 When I send the response back, I am getting empty result in the browser.当我发回响应时,我在浏览器中得到空结果。 As mentioned before, if I hit the url directly, I am getting proper results.如前所述,如果我直接点击 url,我会得到正确的结果。

  2. It is not a preflight OPTIONS request.这不是预检选项请求。

  3. So it can be concluded that it is not a CORS problem.所以可以断定不是CORS问题。 @CrossOrigin annotation works @CrossOrigin 注释有效

I looked at the logs after posting the question.发布问题后,我查看了日志。 So this question can be closed as it is incorrect.所以这个问题可以关闭,因为它是不正确的。 If I am not able to fix the empty response problem, I will post a separate question as this question title is misleading.如果我无法解决空响应问题,我将发布一个单独的问题,因为此问题标题具有误导性。

Thank you all for the response.谢谢大家的回应。

I am using it in this way to allow requests from all origins.我以这种方式使用它来允许来自所有来源的请求。 It is working for me for all of my projects.它对我的所有项目都有效。

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);

    }
}

I've only ever configured CORS at the application level, but the documentation for the @CrossOrigin annotation says that it allows all origins by default, so you might want to try @CrossOrigin() instead of @CrossOrigin(origins = "*")我只在应用程序级别配置过 CORS,但是 @CrossOrigin 注释的文档说它默认允许所有来源,所以你可能想尝试@CrossOrigin()而不是@CrossOrigin(origins = "*")

The documentation also says that it supports "the HTTP methods specified in the @RequestMapping annotation", so you may need to add the OPTIONS method in addition to GET or POST, or whatever method you are currently using (CORS requires support for the OPTIONS method).该文档还说它支持“@RequestMapping 注释中指定的 HTTP 方法”,因此除了 GET 或 POST 或您当前使用的任何方法之外,您可能还需要添加 OPTIONS 方法(CORS 需要支持 OPTIONS 方法) )。

You can just make use of @CrossOrigin in your api endpoint and not mention origin.您可以在 api 端点中使用 @CrossOrigin 而不要提及来源。

Specifying origin may cause impacts on multiple layers of environments too.指定来源也可能对多层环境造成影响。

Keep in mind Access-Control-Allow-Origin: * is only used if you don't have any authentication method (requests without credentials).请记住Access-Control-Allow-Origin: *仅在您没有任何身份验证方法(没有凭据的请求)时使用。 See:看:

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

If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源

Don't use 'no-cors' in your fetch call, because you'll get opaque responses.不要在fetch调用中使用'no-cors' ,因为你会得到不透明的响应。 Either specify 'cors' or don't specify anything.指定'cors'或不指定任何内容。

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

Actually, when you get that 200 OK but opaque response it's not a problem from the server anymore.实际上,当您得到200 OKopaque响应时,它不再是来自服务器的问题。 The response is 200, but the data is opaque because the frontend is probably setting 'no-cors' or similar.响应是 200,但数据是不透明的,因为前端可能设置了“no-cors”或类似设置。 See:看:

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

Regarding the backend, in Spring Boot (w/Kotlin) I'm using this to send Access-Control-Allow-Origin: * header, based on spring-boot-starter-security library.关于后端,在 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()
    }
}

Just http.cors()只是http.cors()

Oh, and it may be a piece of trivial advice but if you are messing with configurations, do restart your server each time, otherwise, chances are you are refreshing the frontend client but the server is stuck with previous attempts.哦,这可能是一条微不足道的建议,但是如果您弄乱了配置,请每次都重新启动服务器,否则,您很可能正在刷新前端客户端,但服务器会卡在以前的尝试中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM