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

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

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

问题

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

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

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

  1. version: '3'
  2. services:
  3. footysim-db:
  4. restart: always
  5. container_name: footysim-db
  6. image: 'mysql:5.7.30'
  7. environment:
  8. MYSQL_ROOT_PASSWORD: password
  9. MYSQL_DATABASE: football_simulation
  10. MYSQL_USER: user
  11. MYSQL_PASSWORD: password
  12. ports:
  13. - '3308:3306'
  14. volumes:
  15. - './initial.sql:/docker-entrypoint-initdb.d/initial.sql'
  16. footysim-server:
  17. restart: always
  18. image: 'DOCKERHUB:PROJECT'
  19. expose:
  20. - '8080'
  21. ports:
  22. - '8080:8080'
  23. environment:
  24. SPRING_DATASOURCE_URL: jdbc:mysql://footysim-db:3306/football_simulation?useSSL=false&allowPublicKeyRetrieval=true
  25. SPRING_DATASOURCE_USERNAME: user
  26. SPRING_DATASOURCE_PASSWORD: password
  27. depends_on:
  28. - footysim-db

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

  1. 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:

  1. 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:

  1. version: '3'
  2. services:
  3. footysim-db:
  4. restart: always
  5. container_name: footysim-db
  6. image: 'mysql:5.7.30'
  7. environment:
  8. MYSQL_ROOT_PASSWORD: password
  9. MYSQL_DATABASE: football_simulation
  10. MYSQL_USER: user
  11. MYSQL_PASSWORD: password
  12. ports:
  13. - '3308:3306'
  14. volumes:
  15. - './initial.sql:/docker-entrypoint-initdb.d/initial.sql'
  16. footysim-server:
  17. restart: always
  18. image: 'DOCKERHUB:PROJECT'
  19. expose:
  20. - '8080'
  21. ports:
  22. - '8080:8080'
  23. environment:
  24. SPRING_DATASOURCE_URL: jdbc:mysql://footysim-db:3306/football_simulation?useSSL=false&allowPublicKeyRetrieval=true
  25. SPRING_DATASOURCE_USERNAME: user
  26. SPRING_DATASOURCE_PASSWORD: password
  27. depends_on:
  28. - footysim-db

And in my application-properties in Spring Boot:

  1. 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 标头。

以下是代码片段:

  1. public class CorsFilter implements Filter {
  2. @Override
  3. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
  4. throws IOException, ServletException {
  5. String path = ((HttpServletRequest) req).getServletPath();
  6. if (path.contains("abcd-在contextPath之后的api路径") || path.contains("abcd-在contextPath之后的api路径")) {
  7. HttpServletResponse response = (HttpServletResponse) res;
  8. HttpServletRequest request = (HttpServletRequest) req;
  9. response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
  10. response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
  11. response.setHeader("Access-Control-Max-Age", "3600");
  12. response.setHeader("Access-Control-Allow-Credentials", "true");
  13. response.setHeader("Access-Control-Allow-Headers", "*");
  14. }
  15. chain.doFilter(req, res);
  16. }
  17. @Override
  18. public void init(FilterConfig filterConfig) {}
  19. @Override
  20. public void destroy() {}
  21. }
英文:

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:

  1. public class CorsFilter implements Filter {
  2. @Override
  3. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
  4. throws IOException, ServletException {
  5. String path = ((HttpServletRequest) req).getServletPath();
  6. if(path.contains("abcd- api path after contextPath ")||path.contains("abcd- api path after contextPath ")) {
  7. HttpServletResponse response = (HttpServletResponse) res;
  8. HttpServletRequest request = (HttpServletRequest) req;
  9. response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
  10. response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
  11. response.setHeader("Access-Control-Max-Age", "3600");
  12. response.setHeader("Access-Control-Allow-Credentials", "true");
  13. response.setHeader("Access-Control-Allow-Headers", "*");
  14. }
  15. chain.doFilter(req, res);
  16. }
  17. @Override
  18. public void init(FilterConfig filterConfig) {}
  19. @Override
  20. public void destroy() {}
  21. }

答案2

得分: 0

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

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

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

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

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:

确定