CORS - Cross-origin Resource Sharing

1. CORS请求特征

ET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0…

Origin字段表明本次请求来自于哪个域,服务器会根据这个值来决定是否同意这次请求。
如果Origin指定的源不在允许范围内则服务器返回正常响应,浏览器判断响应中没有Access-Control-Allow-Origin字段,则会抛出跨域错误。
如果允许访问,响应头会带几个字段:

Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar

上面的头信息之中,有三个与CORS请求相关的字段,都以Access-Control-开头。

(1)Access-Control-Allow-Origin(ACAO)

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

(2)Access-Control-Allow-Credentials(ACAC)

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

(3)Access-Control-Expose-Headers(ACEH)

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

另外一个常用的跨域资源方法是JSONP方法,只是JSONP支持GET请求,而CORS支持除IE10以下的所有浏览器中的请求方法。

2. 服务端处理CORS

CORS主要工作在于服务端,可以在代码层面控制,也可以通过Nginx配置。

如需要对某个接口进行跨域配置,如api/a

  1. location ^~ /api/v1 {
  2. add_header 'Access-Control-Allow-Origin' "$http_origin"; // $http_origin为发出请求的域
  3. add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
  4. add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type ';
  5. add_header 'Access-Control-Allow-Credentials' 'true';
  6. if ($request_method = 'OPTIONS') {
  7. add_header 'Access-Control-Allow-Origin' "$http_origin";
  8. add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
  9. add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type ';
  10. add_header 'Access-Control-Allow-Credentials' 'true';
  11. add_header 'Access-Control-Max-Age' 1728000; # 20 天
  12. add_header 'Content-Type' 'text/html charset=UTF-8';
  13. add_header 'Content-Length' 0;
  14. return 200;
  15. }
  16. # 这下面是要被代理的后端服务器,它们就不需要修改代码来支持跨域了
  17. proxy_pass http://127.0.0.1:8085;
  18. proxy_set_header Host $host;
  19. proxy_redirect off;
  20. proxy_set_header X-Real-IP $remote_addr;
  21. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  22. proxy_connect_timeout 60;
  23. proxy_read_timeout 60;
  24. proxy_send_timeout 60;
  25. }

```