将本地 React 前端连接到本地 Spring Boot 中间件应用程序时出现 CORS 错误

Posted

技术标签:

【中文标题】将本地 React 前端连接到本地 Spring Boot 中间件应用程序时出现 CORS 错误【英文标题】:CORS error when connecting local React frontend to local Spring Boot middleware application 【发布时间】:2018-08-09 11:58:19 【问题描述】:

我正在使用 React 开发一个前端应用程序,该应用程序连接到一个用 Spring boot 编写的中间件服务。 我正在尝试从前端调用端点,如下所示:

return axios.post('http://localhost:8085/workshop/client/createClient', username)
.then((response) => 
  console.log('Success')
)
.catch((error) => console.log(error));

每当我在浏览器中发出请求时,我都会收到以下错误:

OPTIONS http://localhost:8085/workshop/client/createClient 401 ()

Failed to load http://localhost:8085/workshop/client/createClient: Response for preflight has invalid HTTP status code 401.

据我了解,这是因为我的中间件应用程序阻止了预检请求。 在网上阅读了一些关于启用此功能的信息后,我在我的 Spring Boot 应用程序中添加了一个 CorsFilter:

@Slf4j
public class CORSFilter implements Filter 
  private static final String ONE_HOUR = "3600";

  @Override
  public void init(FilterConfig filterConfig) throws ServletException 
  

  @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-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", ONE_HOUR);
    response.setHeader("Access-Control-Allow-Headers", "X-Requested-With,Origin,Content-Type, Accept, x-device-user-agent, Content-Type");

    if (req instanceof HttpServletRequest) 
       HttpServletRequest httpServletRequest = (HttpServletRequest) req;
       if (httpServletRequest.getHeader(HttpHeaders.ORIGIN) != null
          && httpServletRequest.getMethod().equals(HttpMethod.OPTIONS.name())
          && httpServletRequest.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null) 
          log.debug("Received an OPTIONS pre-flight request.");
          return;
       
    
    chain.doFilter(req, res);
  

  @Override
  public void destroy() 
  

@Configuration
public class MvcConfiguration 

 @Bean
 public FilterRegistrationBean corsFilter() 
   FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
   filterRegistrationBean.setFilter(new CORSFilter());
   filterRegistrationBean.addUrlPatterns("/*");
   filterRegistrationBean.setOrder(0);
   return filterRegistrationBean;
 

这是一个端点示例:

 @PostMapping("/createClient")
 public ResponseEntity<?> createClient(@RequestBody CreateClientDto clientDto) 
    try 
     ...
     return new ResponseEntity<>(responseBody, OK);
     catch (Exception e ...) 
  

任何帮助将不胜感激:)

更新:我的请求的 url 略有错误(因此是 404)。我已经更新了错误信息。我似乎仍然遇到 CORS 问题。

这些是我可以在开发工具中看到的响应标头:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:access-control-allow-credentials, access-control-allow-methods, access-control-allow-origin, allow, content-type
Access-Control-Allow-Methods:POST
Access-Control-Allow-Origin:http://localhost:3000
Allow:GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Cache-Control:no-cache, no-store, max-age=0, must-revalidate
Content-Length:0
Date:Thu, 01 Mar 2018 14:06:38 GMT
Expires:0
Pragma:no-cache
Strict-Transport-Security:max-age=31536000 ; includeSubDomains
Vary:Origin
WWW-Authenticate:Basic realm="Spring"
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

还有请求头:

OPTIONS /workshop/client/createClient HTTP/1.1
Host: localhost:8085
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) 
AppleWebKit/537.36 (Khtml, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Access-Control-Request-Headers: access-control-allow-credentials,access-control-allow-methods,access-control-allow-origin,allow,content-type
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,da;q=0.7

【问题讨论】:

404 似乎表示找不到 URL http://localhost:8085/createClient 【参考方案1】:

我也有这个问题,但请允许我以更简单的沟通方式给出直接的答案。

首先,你必须告诉你的服务器(Spring boot java),关于客户端(Reactjs)URL

比如spring boot大部分时候使用http://localhost:8080和Reactjsuses http://localhost:3000

所以你必须导航到 Spring boot java 中的控制器,并允许 Reactjs 的 URL 被授予服务器中可访问性的权限(Spring boot)。这将帮助您摆脱 CORS 问题。

我们如何在 Spring Boot 中做到这一点?只需添加 @CrossOrigin 注释,指定 Reactjs URL 链接,如下所示:

例如:

    @GetMapping("/orphans")
    @CrossOrigin(origins = "http://localhost:3000")
    Iterable<Student> read() 
        return studentService.findAll();
    

上面的方法是列出所有的孤儿,所以我给了 Reactjs URL 链接权限然后我摆脱了 CORS 问题。

编码愉快。

【讨论】:

【参考方案2】:

Controller.java

请参考以下示例代码来解决此问题。

@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping(value="/sample", method = RequestMethod.GET, produces = "application/json")

public Student getStudent()

【讨论】:

【参考方案3】:

这是一个标准的 CORS 问题,这基本上意味着用户代理,即http://localhost:3000 没有访问http://localhost:8085 资源的权限。您可以通过https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS了解更多信息。

您的请求标头应准确映射到服务器规则。将任何参数保留为* 将不起作用。

例如,如果您的请求标头包含以下内容:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: <your custom headers>

然后,服务器规则显示映射您的请求标头:

Access-Control-Request-Method: GET, PUT, DELETE, POST
Access-Control-Request-Headers: <your custom headers>

如果有帮助请告诉我!

【讨论】:

感谢您的帮助。不幸的是,我仍然看到同样的问题。我是否缺少请求或响应的标头?我已经用开发工具中可以看到的标题更新了问题 抱歉回复晚了,我这几天比较忙。随着您对问题的更新,我可以看到您的请求标头与服务器规则不匹配。例如,Access-Control-Allow-HeadersAccess-Control-Allow-Header 不匹配。服务器上设置的规则和你的请求头中发送的规则必须完全相同【参考方案4】:

问题似乎已解决。我错过了 Accept 请求标头(感谢@Anadi Sharma),并且我还拥有 spring-boot-starter-security 作为依赖项,它似乎未经授权返回。我也不需要 CorsFilter,最后我只是在端点上使用了@CrossOrigin 注释。

【讨论】:

请接受请求标头是什么意思。【参考方案5】:

在 fetch 中添加下面的代码行

  export function getData(endpoint = '/', request = ) 
    let url = endpoint;
    let req = Object.assign(
      
        headers: 
          Accept: 'application/json',
          'Content-Type': 'application/json',
          'Access-Control-Allow-Origin': '*',
        ,
      ,
      request
    );
    console.log('url,req', url, req);
    return fetch(url, req).then(handleResponse).catch(handleErrors);
  

并在 Rest Controller 类下面添加以下行

@RestController
@CrossOrigin(origins = "*", allowedHeaders = "*")
class TestController

希望这会有所帮助:)

【讨论】:

以上是关于将本地 React 前端连接到本地 Spring Boot 中间件应用程序时出现 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章

无法将 Spring 云配置服务器连接到本地存储库窗口

将 Spring Cloud 配置服务器连接到本地 git repo 失败

我正在尝试将我的本地 spring boot 应用程序连接到我的 heroku postgres db

无法通过 Spring Boot 将 Docker Desktop Kubernetes (Windows) 服务连接到本地 Postgres db

无法将本机反应连接到本地主机

react-apollo 没有连接到我的 graphql 本地服务器