简体   繁体   English

由于 CORS ZC5FD214CDD0D2B3B422Z2E73B022BA5C,无法使 Spring 引导 API 请求

[英]Unable To Make Spring Boot API Request Due To CORS Docker

I have a React frontend app that makes an API call to a Spring boot app.我有一个 React 前端应用程序,它对 Spring 启动应用程序进行 API 调用。

Both are in separate docker containers.两者都在单独的 docker 容器中。 When it's run locally everything is fine, however after deployment, when the call is made, I get a CORS error:当它在本地运行时,一切都很好,但是在部署之后,当调用时,我得到一个 CORS 错误:

Access to fetch at 'http://xx.xx.xxx.xx:8080/simulations/1/ratings/1' from origin 'http://xx.xx.xxx.xx:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.

I'm not sure why this is the case.我不确定为什么会这样。 To my mind I've coded up everything to allow CORS access (as I said it works locally, so I don't understand why it fails after deployment. I've read up a bit about docker and localhost but it just seems quite confusing to me at the moment.在我看来,我已经编写了所有代码以允许 CORS 访问(正如我所说它在本地工作,所以我不明白为什么它在部署后失败。我已经阅读了一些关于 docker 和 localhost 的信息,但它看起来很混乱对我来说。

This is my Java Security code from WebSecurityConfigurerAdapter :这是我来自WebSecurityConfigurerAdapter的 Java 安全代码:

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://xx.xx.xxx.xx:3000"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

docker-compose.yml is as follows: docker-compose.yml如下:

version: '3'
services:     
  application-server:
    restart: always
    image: 'myhub/app-server:cors'
    expose:
      - '8080'
    ports:
      - '8080:8080'
    networks:
      - local      
  application-client:
    restart: always
    image: 'myhub/app-client:cors'
    ports:
      - '3000:80'
    stdin_open: true
    depends_on:
      - application-server
    networks:
      - local
networks: 
  local:
    driver: bridge      

And finally the nginx.conf :最后是nginx.conf

http
{
  server_tokens off;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  upstream backend
  {
    server xx.xx.xxx.xx:8080;
  }

  server
  {

    listen 80;
    server_name localhost;

    access_log /var/log/nginx/host.access.log;
    error_log /var/log/nginx/host.error.log;


    root /var/www;
    index index.html index.htm;

    location ~* \.(?:manifest|appcache|html?|xml|json)$
    {
      expires -1;
    }

    location ~* \.(?:css|js)$
    {
      try_files $uri =404;
      expires 1y;
      access_log off;
      add_header Cache-Control "public";
    }

    # Any route containing a file extension (e.g. /devicesfile.js)
    location ~ ^.+\..+$
    {
      try_files $uri =404;
    }

    location /
    {

      root /var/www;
      index index.html;
      autoindex on;
      set $fallback_file /index.html;
      if ($http_accept !~ text/html)
      {
        set $fallback_file /null;
      }
      if ($uri ~ /$)
      {
        set $fallback_file /null;
      }
      try_files $uri $fallback_file;

      if ($request_method = 'OPTIONS')
      {
        add_header 'Access-Control-Allow-Origin: $http_origin');
        add_header 'Access-Control-Allow-Origin: GET, POST, DELETE, PUT, PATCH, OPTIONS');
        add_header 'Access-Control-Allow-Credentials: true');
        add_header 'Vary: Origin');

      }

      add_header 'Access-Control-Allow-Origin' "$http_origin" always;
      add_header 'Access-Control-Allow-Credentials' 'true' always;
      add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, PATCH, DELETE, OPTIONS' always;
      add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;

    }
  }
}

What do I need to do with the containers to allow CORS access?我需要对容器做什么才能允许 CORS 访问?

First: to benefit from CORS, you don't need to focus on http client configuration.第一:要从 CORS 中受益,您无需关注 http 客户端配置。
The authorization is allowed only by the backend that answers to the question: is that host, port, request acceptable?只有回答以下问题的后端才允许授权:该主机、端口、请求是否可接受? Contrary to CSRF that requires configuration both client and server.与需要配置客户端和服务器的 CSRF 相反。

I mention that since you expose your client conf.我提到这一点,因为您公开了您的客户配置文件。

In any way, in Spring Boot (backend of course), we enable CORS declaratively from the WebSecurityConfigurerAdapter.configure(HttpSecurity http) method as simply as:无论如何,在 Spring 引导(当然是后端)中,我们通过WebSecurityConfigurerAdapter.configure(HttpSecurity http)方法以声明方式启用 CORS,如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
  http.cors()...
}

The cors() javadoc states that: cors() javadoc 指出:

Adds a CorsFilter to be used.添加要使用的 CorsFilter。 If a bean by the name of corsFilter is provided, that CorsFilter is used.如果提供了名为 corsFilter 的 bean,则使用该 CorsFilter。 Else if corsConfigurationSource is defined, then that CorsConfiguration is used.否则,如果定义了 corsConfigurationSource,则使用该 CorsConfiguration。

So first, check that.所以首先,检查一下。

Then you have three options:然后你有三个选择:
– to do no additional thing. – 不做任何额外的事情。 In this case, Spring security will use the default class provided by Spring security and the default CorsConfigurationSource bean associated to.在这种情况下,Spring 安全将使用 Spring 安全提供的默认 class 和关联的默认 CorsConfigurationSource bean。
– to declare a bean named corsFilter . – 声明一个名为corsFilter的 bean。 In this case, Spring security will use it instead of the default.在这种情况下,Spring 安全将使用它而不是默认值。
– to declare a bean named corsConfigurationSource . – 声明一个名为corsConfigurationSource的 bean。 In that case, Spring will use the default CorsFilter with the custom corsConfigurationSource declared by the application.在这种情况下,Spring 将使用默认的 CorsFilter 和应用程序声明的自定义corsConfigurationSource

You used the last way.你用的是最后一种方式。

If it is not enough, you may have something in your WebSecurity configs that prevents the CORS filter to be handled at the right time.如果这还不够,您的WebSecurity配置中可能有一些东西会阻止在正确的时间处理 CORS 过滤器。
Add that property and take time to analyse what Spring Security does about CORS:添加该属性并花时间分析 Spring Security 对 CORS 所做的事情:

logging.level.org.springframework.security=DEBUG

I wrote that post some months ago.几个月前我写了那篇文章 Maybe it could help you.也许它可以帮助你。

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

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