Nginx配置CORS实现资源跨域

同源策略

同源策略是Web应用程序安全模型中的一个重要概念。根据该策略,Web浏览器允许第一个Web页面中包含的脚本访问第二个Web页面中的数据,但前提是两个Web页面具有相同的源。同源定义为协议,主机名和端口号相同的组合。此策略可防止一个页面上的恶意脚本通过该页面的文档对象模型访问另一个网页上的敏感数据。

AJAX规避同源策略三种方式

JSONP:请求阶段:浏览器创建一个 script 标签,并给其src 赋值。发送请求:当给script的src赋值时,浏览器就会发起一个请求。数据响应:服务端将要返回的数据作为参数和函数名称拼接在一起(格式类似”jsonpCallback({name: 'abc'})”)返回。当浏览器接收到了响应数据,由于发起请求的是 script,所以相当于直接调用 jsonpCallback 方法,并且传入了一个参数。JSONP只支持GET请求,AJAX支持GET和POST请求。

WebSocket:使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

CORS:跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。

利用Nginx高效解决跨域问题

跨域分为简单跨域和复杂跨域。简单跨域不会发送OPTIONS请求,而复杂跨域会发送一个预检查OPTIONS请求。复杂跨域的条件是:

  • 非GET、HEAD、POST请求。
  • POST请求的Content-Type不是application/x-www-form-urlencoded, multipart/form-data, 或text/plain。
  • 添加了自定义header,例如Token。

跨域请求浏览器会在Headers中添加Origin,通常情况下不允许用户修改其值。
关于同源策略,当请求了于自身域名不相同的url时,会出现如下信息提示错误:

Access to XMLHttpRequest at ‘***’ from origin ‘***’ 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.

实现:

#通配符* 全部允许 存在安全问题(不推荐)
server {
        ...
        location / {
            # 允许 所有头部 所有域 所有方法
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Headers' '*';
            add_header 'Access-Control-Allow-Methods' '*';
            # OPTIONS 直接返回204
            if ($request_method = 'OPTIONS') {
                return 204;
            }
        }
        ...
    }
#多域名配置 配置多个域名在map中 只有配置过的允许跨域
map $http_origin $corsHost {
        default 0;
        "~https://yourdomain_1" https://yourdomain_1;
        "~https://yourdomain_2" https://yourdomain_2;
        "~https://yourdomain_3" https://yourdomain_3;
    }
    server {
        ...
        location / {
            # 允许 所有头部 所有$corsHost域 所有方法
            add_header 'Access-Control-Allow-Origin' $corsHost;
            add_header 'Access-Control-Allow-Headers' '*';
            add_header 'Access-Control-Allow-Methods' '*';
            # OPTIONS 直接返回204
            if ($request_method = 'OPTIONS') {
                return 204;
            }
        }
        ...
    }

CRUL跨域测试

GET请求成功返回跨域头:

~ curl -I -H "Origin: http://localhost" http://localhost
HTTP/1.1 403 Forbidden
Server: nginx/1.15.6
Date: Wed, 14 Nov 2018 07:56:01 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 153
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token

OPTIONS预检请求成功返回跨域头:

~ curl -I -H "Origin: http://localhost" -X OPTIONS http://localhost
HTTP/1.1 204 No Content
Server: nginx/1.15.6
Date: Wed, 14 Nov 2018 08:19:36 GMT
Connection: keep-alive
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Accept, Authorization, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, Origin, User-Agent, X-Requested-With, Token, x-access-token
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=utf-8
Content-Length: 0
点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注