Nginx解决CORS跨域解决方案

首先通读下 MDN 关于 CORS 的 定义,了解跨域的含义及简单请求和复杂请求等的定义。文中的内容不赘述,如今说解决方案。

经过定义咱们能够,简单请求与复杂请求的差异是复杂请求会自动发出一个 OPTIONS 的预检请求,当请求获得确认后,才开始真正发送请求。webpack

综上,咱们要解决两个问题:web

  1. OPTIONS 请求的正确响应
  2. 跨域请求正确响应

Q1: OPTIONS 请求的正确响应

解决的方式有多种,既能够在Web Server解决,也能够在源码层解决。由于问题比较广泛,故咱们选择在Web Server解决,下面咱们以 Nginx 为例,说明解决方案。api

假设访问的地址为 /example , Nginx 配置以下:跨域

location /example {
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
  }

为了解决跨域问题,添加以下内容:缓存

location /example {
+   if ($request_method = 'OPTIONS') {
+       add_header Access-Control-Allow-Origin *;
+       add_header Access-Control-Max-Age 1728000;
+       add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+       add_header Access-Control-Allow-Headers  'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
+       add_header Content-Type' 'text/plain; charset=utf-8';
+       add_header Content-Length 0 ;
+       return 204;
+    }


    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
   }

解释:

if ($request_method = 'OPTIONS') {...} 当请求方法为 OPTIONS 时:webpack-dev-server

  1. 添加容许源 Access-Control-Allow-Origin 为 * (可根据业务须要更改)
  2. 添加缓存时长 Access-Control-Max-Age,当下次请求时,无需再发送 OPTIONS 请求
  3. 添加容许的方法,容许的首部
  4. 添加一个内容长度为0,类型为 text/plain; charset=utf-8 , 返回状态码为 204 的首部

至此,完成 OPTIONS 请求的正确响应。spa

Q2: 跨域请求正确响应

添加以下内容:3d

location /example {
   if ($request_method = 'OPTIONS') {
       add_header Access-Control-Allow-Origin *;
       add_header Access-Control-Max-Age 1728000;
       add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
       add_header Access-Control-Allow-Headers  'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
       add_header Content-Type' 'text/plain; charset=utf-8';
       add_header Content-Length 0 ;
       return 204;
    }

+   if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {
+     add_header  Access-Control-Allow-Origin $http_origin;
+     add_header  Access-Control-Allow-Credentials true;
+     add_header  Access-Control-Allow-Methods GET,POST,OPTIONS;
+     add_header  Access-Control-Expose-Headers Content-Length,Content-Range;
+   }

    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080/;
   }

解释:

if ($http_origin ~* (https?://(.+\.)?(example\.com$))) {...}, 当 origin 为合法域名(可根据业务调整或去除合法域名验证)时:代理

  1. 添加容许源Access-Control-Allow-Origin为 $http_origin (可根据业务须要更改)
  2. 添加容许认证Access-Control-Allow-Credentials为 true ,容许接收客户端 Cookie(可根据业务须要更改。 但要注意,当设置为true时,Access-Control-Allow-Origin 不容许设置为 *)
  3. 添加容许的方法,暴露的首部

至此,完成跨域请求正确响应。code

以上,是对跨域请求在Web Server的解决方案,主要是经过响应 OPTIONS 方法和添加容许源来解决。

固然,若是本地开发中,能够在利用 webpack-dev-server 的 proxy 选项来快速解决跨域问题:
示例以下:

// webpack.congf.js

module.exports = {
  //...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {'^/api' : ''}
      }
    }
  }
}

当访问地址如 /api/foo?q=bar 时,则经过代理访问的实际地址是: http://localhost:3000/foo?q=bar

CORS跨域请求并不魔幻,理解 CORS 的含义,根据规则去找方法就迎刃而解了。但愿能帮助到你们。

以上。

相关文章
相关标签/搜索