nginx 添加http header头,进行跨域设置(“add_header“ directive is not allowed)

有时候我们想对某个项目进行跨域访问限制,不管是静态目录文件,还是其他。动态文件还好说,可以在代码里添加,如php:

header('Access-Control-Allow-Origin: http://www.a.com')
header('Access-Control-Allow-Origin: http://www.b.com')

但静态目录文件,如图片等,就麻烦了,别急,这时就可以考nginx解决

解决方案

location ~* \.ico|jpg|gif|png|js|css|woff2|ttf$ {
        if ($http_origin ~ [a-z]+\.a|b\.com$){ # xxx.a.com或xxx.b.com域名才可以访问
            add_header Access-Control-Allow-Origin $http_origin;
            add_header Access-Control-Request-Method GET;
        }
        root /usr/local/ad/ui; #存放静态文件的路径
        expires 1h;
    }

当然,仅在localtion下设置有效范围不够大,如果我们想对整个server进行设置,可以做如下配置:

server {
    set $cors_origin "";
    set $cors_cred   "";
    
    if ($http_origin ~ "^https.[a-z]+\.a|b\.com$") {
            set $cors_origin $http_origin;
            set $cors_cred   true;
    }
    add_header Access-Control-Allow-Origin      $cors_origin;
    add_header Access-Control-Allow-Credentials $cors_cred;
    add_header Access-Control-Allow-Headers    'Origin, X-Requested-With, Content-Type, Accept';#服务端可以接收的header
    add_header Access-Control-Allow-Methods     'GET,POST';
    add_header Access-Control-Allow-Credentials, true;#服务端接收认证信息,如cookie
}

注意 server里的配置不能与location里的一样,会报错:nginx: [emerg] "add_header" directive is not allowed here in /usr/local......

关于跨域的认识

  • W3C标准规定,http请求头的origin(源地址)与目的地址在协议(http1.1,https等),端口,域名(ip)任何一个不一致就会触发跨域拦截机制。
  • 为什么只有ajax会触发跨域?
    其实这个问题问的并不好,回答这个问题前,我们要了解跨域可以简单的分为两种:简单请求和复杂请求

1: 简单请求 :
http请求方法的值限于三者之一:get,put,post;
Content-Type的值仅限于三者之一:text/plain,multipart/form-data,application/x-www-form-urlencoded;
除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:

Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width

2:复杂请求
除了简单请求都是复杂请求,我们大多数时候都是 ajax请求的Content-Type:application/json 这样的复杂请求导致的。
简单请求如果设置了Authentication认证header也会让请求“升级”为复杂请。

简单请求相比于复杂请求少了一步 预检请求,也就是http的OPTIONS请求

这些规则在现代浏览器都是有实现的

关于nginx【 if ,正则匹配】

和shell规则很像。

  1. 正则表达式匹配:

=:等值比较;

~:与指定正则表达式模式匹配时返回“真”,区分字符大小写;

~*:与指定正则表达式模式匹配时返回“真”,不区分字符大小写;

!~:与指定正则表达式模式不匹配时返回“真”,区分字符大小写;

!~*:与指定正则表达式模式不匹配时返回“真”,不区分字符大小写;

  1. 文件及目录匹配判断:

-f, !-f:判断指定的路径是否为存在且为文件;

-d, !-d:判断指定的路径是否为存在且为目录;

-e, !-e:判断指定的路径是否存在,文件或目录均可;

-x, !-x:判断指定路径的文件是否存在且可执行;

参考

HTTP访问控制(CORS)
Nginx Config for Cors - add_header directive is not allowed
为什么postman调接口不会跨域而浏览器会
ebay cors-filter 服务

你可能感兴趣的:(nginx,nginx)