Nginx CORS 与 Angular

Posted

技术标签:

【中文标题】Nginx CORS 与 Angular【英文标题】:Nginx CORS with Angular 【发布时间】:2016-11-16 15:47:00 【问题描述】:

所以我这几天一直在拔头发。 我有一个后端服务器,使用 nginx、Gunicorn 和 Django。我将它用作 REST 服务器,使用 Django Rest Framework,并使用带有 Django Rest Auth 的令牌身份验证。此服务器的地址是 api.dev.mysite.com

这个服务器是使用 AngularJS 从前端接口调用的,也由 Nginx 处理,地址为 dev.mysite.com

一切都在本地运行,正如您所见,这两个域是不同的。每当我尝试从前端向后端发出请求时,都会收到以下错误:

Failed to load resource: Origin https://dev.mysite.com is not allowed by Access-Control-Allow-Origin.

我知道你的想法:简单,只需将add_header 'Access-Control-Allow-Origin' 'http://dev.mysite.com'; 添加到后端的nginx.conf 文件中,一切都会正常运行,例如here. 或here.

但事实并非如此。我尝试了一切,将其移动到不同的位置,放置“*”而不是地址,启用和禁用 SSL ...... 唯一有效的是当我在浏览器中手动禁用跨域限制时。最好的部分是,当我禁用这些限制时,我可以在浏览器的调试控制台中看到 Access-Control-Allow-Origin 标头设置为 http://dev.mysite.com!

知道可能出了什么问题吗?

这是我的nginx.conf 文件:

worker_processes 1;

user me staff;
error_log /tmp/nginx.error.log;

events 
  worker_connections 1024; # increase if you have lots of clients
  accept_mutex off; # set to 'on' if nginx worker_processes > 1


http 
  include mime.types;
  default_type application/octet-stream;
  access_log /tmp/nginx.access.log;
  sendfile on;

  upstream app_server 
    # for UNIX domain socket setups
     server unix:/tmp/gunicorn.sock fail_timeout=0;
  

  # Common SSL Settings
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;

  ssl_prefer_server_ciphers on;
  ssl_ciphers ALL:!ADH:!EXP:!LOW:!RC2:!3DES:!SEED:!RC4:+HIGH:+MEDIUM:!kEDH;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  server 
    # if no Host match, close the connection to prevent host spoofing
     listen 80 default_server;
     return 444;
  

  server 
     listen 443 ssl;
     server_name api.dev.mysite.com;

     # Self-signed certificate.
     ssl_certificate ssl/nginx-selfsigned.crt;
     ssl_certificate_key ssl/nginx-selfsigned.key;

     access_log /tmp/api.dev.intelligence.access.log;
     error_log /tmp/api.dev.intelligence.error.log;

     location / 
        add_header 'Access-Control-Allow-Origin' 'https://dev.mysite.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept-Encoding';

        if ($request_method = 'OPTIONS') 
          add_header 'Access-Control-Max-Age' 1728000;
          add_header 'Content-Type' 'text/plain charset=UTF-8';
          add_header 'Content-Length' 0;
          return 204;
        

        proxy_pass http://127.0.0.1:9000;
        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-for $remote_addr;
        proxy_set_header    X-Forwarded-Protocol $scheme;
      
  

  server 
    client_max_body_size 4G;

    # Self-signed certificate.
    ssl_certificate ssl/nginx-selfsigned-front.crt;
    ssl_certificate_key ssl/nginx-selfsigned-front.key;

    # Listen on 80 and 443
    listen 80;
    listen 443 ssl;
    listen [::]:443 ssl;

    # set the correct host(s) for your site
    server_name dev.mysite.com;

    # Redirect all non-SSL traffic to SSL.
    if ($ssl_protocol = "") 
      rewrite ^ https://$host$request_uri? permanent;
    

    keepalive_timeout 5;

    access_log /tmp/dev.intelligence.access.log;
    error_log /tmp/dev.intelligence.error.log;

    location / 
        root /path/to/app/current/;
        index index.html index.htm;   
    

    error_page 500 502 503 504 /500.html;
    location = /500.html 
      root /path/to/app/current/public;
    
  

【问题讨论】:

不是您问题的具体答案,但django-cors-middleware 通过在 django 端与 nginx 进行配置使这更容易。 为了让 CORS 允许您的请求,您需要在服务器端将您的客户端列入 CORS 白名单。如果有帮助,请参阅 this。 感谢您的建议。我安装了 Django CORS 中间件,并在我的 settings.py 中添加了以下几行:CORS_ORIGIN_WHITELIST = ('dev.mysite.com'),但没有解决问题。我也试过CORS_ORIGIN_ALLOW_ALL = True 【参考方案1】:

好的,所以我找到了解决问题的方法。我做了三件事:

    从我的nginx.conf 文件中删除所有“add_header”行。现在看起来像这样:

    location / 
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-for $remote_addr;
        proxy_set_header    X-Forwarded-Protocol $scheme;
    
    

    安装 Django Cors 标头,并将以下行添加到我的 settings.py:

    CORS_ORIGIN_ALLOW_ALL = False
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_WHITELIST = (
        'dev.myapp.com'
    )
    

    在我的 Angular 中的 .config 文件中添加了以下几行:

    $httpProvider.defaults.useXDomain = true;
    $httpProvider.defaults.withCredentials = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
    

    我分别尝试了所有这些东西,但我想这三个都需要。

【讨论】:

以上是关于Nginx CORS 与 Angular的主要内容,如果未能解决你的问题,请参考以下文章

使用 Nginx 的 socket.io 出现 CORS 错误

使用 nginx 和 aws 启用 cors 的正确配置是啥?

(Laravel&Nginx)CORS标题'Access-Control-Allow-Origin'与'(null)'不匹配

73.nginx跨域

Express、Socket.io 和 Nginx 的 CORS 问题

使用CORS解决跨域问题