我已经构建了一个 Angular 应用程序并创建了一个 docker 映像,这使得它在 Nginx 服务器上运行(一旦运行)。对于后端,我也有一个 dockerized 实现。在尝试从后端访问数据时,我遇到了与 CORS 策略相关的错误,因此在浏览器上我看到以下内容:“...已被 CORS 策略阻止:不存在“Access-Control-Allow-Origin”标头...”
为了解决这个问题,我尝试在 Nginx 服务器中进行不同的配置更改,例如:(1)设置 add_header “Access-Control-Allow-Origin” “http://0.0.0.0:8080”,(2)在代理端尝试类似的更改,proxy_set_header “Access-Control-Allow-Origin” “http://0.0.0.0:8080” 等等。但它们都不起作用(注意,“http://0.0.0.0:8080”指的是后端,而 Angularhaving 通过“http://0.0.0.0:7000”访问)。
下面是我的配置文件的示例:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri /index.html = 404;
}
location /api {
proxy_pass http://0.0.0.0:8080;
proxy_set_header "Access-Control-Allow-Origin" "http://0.0.0.0:8080"
}
}
你们能分享一下如何解决这个问题的想法吗?
谢谢!
答案1
实际执行阻止的是 Web 客户端(无论被阻止的 Web 客户端恰好位于您的设置中的何处),因此您需要允许客户端打算与注入的源地址一起使用访问控制允许来源標軸。
客户端在发送请求(这对您来说会失败)之前必须知道此标头和值,因此需要在早期的响应中提供它。
如链接所示,标头语法不包含端口号。据我所知,0.0.0.0 不是 CORS 以与网络服务相同的方式解释的语法,但我没有对此进行测试,并且可能是错误的。
据我所知,标头未指定协议,但仅指定了 fqdn,例如www.example.com。
我猜测特定的 IP 地址可以代替 fqdn,但是我还没有测试过,而且可能是错的。
但是,我使用了链接中指定的通配符语法 (*),这确实有效。如果可能,最好使用更具体的地址,但你可以先从通配符开始,看看标头注入是否有效。
所以我的建议是尝试注射Access-Control-Allow-Origin: *
。
答案2
不需要在 nginx conf 中添加任何内容,例如 proxy_set_header。您必须在 spring web 应用程序中添加 CORS 来源过滤器并允许来自不同来源的过滤器。
像这样 :
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
log.info("request came for url {}", ((HttpServletRequest) req).getRequestURL());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
response.setHeader("Access-Control-Max-Age", "3600");
if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig config) throws ServletException {
}
}