Nginx通过CROS实现跨域

CROS介绍

什么是CROS

CORS是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

当前几乎所有的浏览器(Internet Explorer 8+, Firefox 3.5+, Safari 4+和 Chrome 3+)都可通过名为跨域资源共享(Cross-Origin Resource Sharing)的协议支持AJAX跨域调用。

Chrome,Firefox,Opera,Safari都使用的是XMLHttpRequest2对象,IE使用XDomainRequest。

简单来说就是跨域的目标服务器要返回一系列的Headers,通过这些Headers来控制是否同意跨域。跨域资源共享(CORS)也是未来的跨域问题的标准解决方案。

CORS提供HTTP Response Header

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Credentials
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Expose-Headers
  • Access-Control-Max-Age

CORS提供HTTP Request Header

  • Access-Control-Request-Method
  • Access-Control-Request-Headers

启用CROS请求

1
2
3
4
5
6
7
# 只允许http://example.com跨域
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Credentials: true # (可选)

# 允许任何域向您提交请求
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true # (可选)

配置Nginx跨域示例

标准示例

1
2
3
4
5
6
7
8
9
10
location /{
# 授权从example.com的请求(必需)
add_header 'Access-Control-Allow-Origin' 'http://example.com';
# 当该标志为真时,响应于该请求是否可以被暴露(可选)
add_header 'Access-Control-Allow-Credentials' 'true';
# 允许脚本访问的返回头(可选)
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Requested-With';
# 指定请求的方法,可以是GET, POST, OPTIONS, PUT, DELETE等(可选)
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
}

允许多个域名跨域访问

方法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
map $http_origin $corsHost {
default 0;
"~http://www.example.com" http://www.example.com;
"~http://m.example.com" http://m.example.com;
"~http://wap.example.com" http://wap.example.com;
}

server
{
listen 80;
server_name www.example2.com;
root /usr/share/nginx/html;
location /
{
add_header Access-Control-Allow-Origin $corsHost;
}
}

方法2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set $cors '';
if ($http_origin ~* 'https?://(localhost|www\.example\.com|m\.example\.com)') {
set $cors 'true';
}

if ($cors = 'true') {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Mx-ReqToken,X-Requested-With';
}

if ($request_method = 'OPTIONS') {
return 204;
}

方法3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location /{
if ( $http_origin ~ http://(.*).example.com){
set $allow_url $http_origin;
}
#CORS(Cross Orign Resource-Sharing)跨域控制配置
#是否允许请求带有验证信息
add_header Access-Control-Allow-Credentials true;
#允许跨域访问的域名,可以是一个域的列表,也可以是通配符*
add_header Access-Control-Allow-Origin $allow_url;
#允许脚本访问的返回头
add_header Access-Control-Allow-Headers 'x-requested-with,content-type,Cache-Control,Pragma,Date,x-timestamp';
#允许使用的请求方法,以逗号隔开
add_header Access-Control-Allow-Methods 'POST,GET,OPTIONS,PUT,DELETE';
#允许自定义的头部,以逗号隔开,大小写不敏感
add_header Access-Control-Expose-Headers 'WWW-Authenticate,Server-Authorization';
#P3P支持跨域cookie操作
add_header P3P 'policyref="/w3c/p3p.xml", CP="NOI DSP PSAa OUR BUS IND ONL UNI COM NAV INT LOC"';
}

方法4

1
2
3
4
5
location / {
if ( $http_origin ~ .*.(example|example1).com ) {
add_header Access-Control-Allow-Origin $http_origin;
}
}
坚持原创技术分享,您的支持将鼓励我继续创作!