英文:
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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论