CORS问题:从DockerHub拉取用于前端开发的Spring/MySQL后端

huangapple go评论78阅读模式
英文:

CORS Issue: Pull Spring/MySQL Backend from DockerHub For Front End Development

问题

我已将一个 Java/MySQL 后端应用推送到了我的私有 Docker Hub。我想要对其进行沙箱处理,以便多个用户可以访问并对该应用进行 API 调用,因为我们希望在 React 中进行一些前端浏览器开发。使用类似 Postman 的 REST 客户端是可以的,但是当我们开始在浏览器中使用时,会遇到 CORS(跨源资源共享)问题:

从源 'http://localhost:3000' 访问 'http://127.0.0.1:8080/simulations/1/ratings/1' 已被 CORS 策略阻止:预检请求的响应未通过访问控制检查:请求的资源上没有 'Access-Control-Allow-Origin' 标头。如果不透明的响应能满足您的需求,请将请求模式设置为 'no-cors',以在禁用 CORS 的情况下获取资源。

我的 docker-compose.yml 文件如下:

version: '3'
services:
  footysim-db:
    restart: always
    container_name: footysim-db
    image: 'mysql:5.7.30'
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: football_simulation
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - '3308:3306'
    volumes:
      - './initial.sql:/docker-entrypoint-initdb.d/initial.sql'
  footysim-server:
    restart: always
    image: 'DOCKERHUB:PROJECT'
    expose:
      - '8080'
    ports:
      - '8080:8080'
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://footysim-db:3306/football_simulation?useSSL=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_USERNAME: user
      SPRING_DATASOURCE_PASSWORD: password
    depends_on:
      - footysim-db

以及在我的 Spring Boot 的 application-properties 中:

project.cors.allowedOrigins=http://$server_ip:3000, http://127.0.0.1:3000

我的配置是否有什么问题?

英文:

I have pushed a java/mysql backend application to my private dockerhub. I would like to sandbox this so multiple users can access, and make API calls to this application as we would like to do some front-end browser development in React. Using a REST client like Postman is fine, but when we start using the browser we start having CORS issues:

Access to fetch at 'http://127.0.0.1:8080/simulations/1/ratings/1' from origin 'http://localhost: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.

My docker-compose.yml file below:

version: '3'
services:
  footysim-db:
    restart: always
    container_name: footysim-db
    image: 'mysql:5.7.30'
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: football_simulation
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - '3308:3306'
    volumes:
      - './initial.sql:/docker-entrypoint-initdb.d/initial.sql'
  footysim-server:
    restart: always
    image: 'DOCKERHUB:PROJECT'
    expose:
      - '8080'
    ports:
      - '8080:8080'
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://footysim-db:3306/football_simulation?useSSL=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_USERNAME: user
      SPRING_DATASOURCE_PASSWORD: password
    depends_on:
      - footysim-db

And in my application-properties in Spring Boot:

project.cors.allowedOrigins=http://$server_ip:3000, http://127.0.0.1:3000

Have I done something wrong with the config?

答案1

得分: 1

以下是翻译好的内容:

我在过去曾遇到过类似的问题。不过与 Docker 无关。
为了实现 CORS(跨源资源共享)功能,我添加了一个自定义过滤器,其中我定义了一个特定的 API 路径,允许使用 CORS 标头。

以下是代码片段:

public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        String path = ((HttpServletRequest) req).getServletPath();
        if (path.contains("abcd-在contextPath之后的api路径") || path.contains("abcd-在contextPath之后的api路径")) {
            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", "*");
        }
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}
英文:

I have faced the similar issue in the past. It was not related to docker though.
As a work around to allow CORS functionality i added a custom filter in which i defined a specific API path to be allowed with CORS headers.

Code snippet below:

public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        String path = ((HttpServletRequest) req).getServletPath();
        if(path.contains("abcd- api path after contextPath ")||path.contains("abcd- api path after contextPath  ")) {
            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", "*");
        }
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

答案2

得分: 0

谢谢,Imran。在同样的思路下,我发现这是解决方案:

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(ImmutableList.of("*"));
    configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}
英文:

Thanks Imran. Along the same lines I found this to be the solution:

  @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH"));must not be the wildcard '*' when the request's credentials mode is 'include'.
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

huangapple
  • 本文由 发表于 2020年9月9日 16:09:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63807373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定