nginx配置跨域(CORS)、防盗链(valid_referers)、缓存(expires)、压缩(gzip)
环境:
centos6/7,nginx-1.9.15.
摘要说明:
上一篇主要讲述nginx下的常用内置变量及if语句;
步骤:
1.跨域
场景:首先我们举例看看什么叫做跨域:
当我们加载static.xxxx.com的页面之后,在js中调用www.xxxx.com接口,这个时候就叫做跨域;因为请求的主体已发生改变,浏览器拒绝执行;
解决方案:
其中解决跨域问题常用的编程方式就是jsonp;
而服务器端解决方式就是cors解决方案:
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求, 从而克服AJAX只能同源使用的限制。
简单请求: 浏览器在跨源AJAX请求的头信息之中,自动在添加一个Origin字段(本次请求来自哪个源 )。 服务器根据这个值,在许可范围内,则在头信息包含 Access-Control-Allow-Origin 。
复杂请求: 会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求OPTIONS
实践:
首先我们写一个html:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="jquery-1.11.2.js" ></script> <script> $(function(){ $.ajax({ async : false, type : "POST", url : "http://cccc1.study.xxxx.cn:2012/cccc/test1.do", data : null, dataType : 'json', success : function(data) { console.log(data) } }); }); </script> </head> <body> <img src="http://cccc1.study.xxxx.cn:2012/test/page1.jpg" /> </body> </html>
此时nginx配置:
server { listen 2012; server_name localhost; location / { root html; } location = /cccc/test1.do { proxy_pass http://127.0.0.1:8888/cccc/test1.do; } error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }
访问页面:http://cccc.study.xxxx:2012/test/page1.html
由于页面的域名和ajax请求的域名不一致所以浏览器报跨域异常:
下面就是nginx的cors配置:
server { listen 2012; server_name localhost; #判断请求域名是否是指定域名的子域名,如果是,则将内置域名赋值给内置变量$allow_url,便于指定Access-Control-Allow-Origin if ( $http_origin ~ http://(.*).xxxx){ set $allow_url $http_origin; } #是否允许请求带有验证信息 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"'; add_header test 1; if ($request_method = 'OPTIONS') { return 204; } location / { root html; } location = /cccc/test1.do { proxy_pass http://pro.baoyjr.com/cccc/test1.do; } error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }
上述配置是判断域名是指定域名的子域名,若是将子域名赋值给内置变量,传递到后续的Access-Control-Allow-Origin;
但Access-Control-Allow-Origin也可以指定全部即*,也可以指定多个即在前面添加多个if即可;
此时访问页面可正常访问,我们可以看下下述请求信息:
整理下整个请求流程:
当chrome发现ajax请求的网址,与当前主域名不一致(跨域)时,会在请求header中追加值页面主域名值,即:origin = http://cccc.study.xxxx.cn;
nginx在接收到ajax请求时,会查看origin值,查看请求域名;此处使用正则来校验,即:只要是xxxx.cn下的网址,都允许访问;返回信息时,nginx追加header值:access-control-allow-origin = cccc.study.xxxx.com(回答浏览器,此域名可以访问)
chrome收到ajax返回值后,查看返回的header中access-control-allow-origin的值,发现其中的值是正是当前的页面主域名,即允许访问,于是执行ajax返回值内容。(ps:若此处access-control-allow-origin不存在,或者值不是此域名,chrome就拒绝执行返回值)
2.防盗链
场景:由于图片链接可以跨域访问,所以图片链接往往被其他网站盗用,从而增加服务器负担;
解决方案:nginx可以通过valid_referers配置进行防盗链配置:
valid_referers
语法:valid_referers [none|blocked|server_names] ...
默认值:none
使用字段:server, location
这个指令在referer头的基础上为 $invalid_referer 变量赋值,其值为0或1。
可以使用这个指令来实现防盗链功能,如果valid_referers列表中没有Referer头的值, $invalid_referer将被设置为1(参照下列)。
server { listen 2013; server_name localhost; location / { root html; } #防盗链,校验加载图片来源是否是指定域名,图片不可直接下载及展示 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { valid_referers *.xxxx.cn; if ($invalid_referer) { return 404; } root html; } error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }
上述配置就可以达到除指定域名及其子域名下的页面可以访问上述格式图片,其他全部返回404;直接访问图片也不可以;
3.缓存
场景:业务中一般存在页面来回切换或加载同样的素材,若每次相同素材加载都需要重新加载是很消耗流量和加重响应速度
解决方案:nginx通过expires配置缓存时间告知浏览器该素材可进行缓存并缓存多长时间;
expires
语法:expires [time|@time-of-day|epoch|max|off]
默认值:expires off
使用字段:http, server, location
这个指令控制是否在应答中标记一个过期时间,如果是,如何标记。
·off 将禁止修改头部中的 Expires和Cache-Control字段。
·epoch 将Expires头设置为1 January, 1970 00:00:01 GMT。
·max 将Expires头设置为31 December 2037 23:59:59 GMT,将Cache-Control最大化到10 years。
·如果将指令设置为一个不带@标记的值,那么过期时间将是应答时间的相对时间(如果这个时间在“modified”之前),或者是文件的修改时间(当"modified"存在,在版本0.7.0和0.6.32可用),并且可以指定一个负的时间,它将Cache-Control头设置为no-cache比较。
·如果指令的值被设置为一个带@标记的值,那么将指定一个绝对的time-of-day过期时间,可以指定两种格式分别为Hh或Hh:Mm,其中H的大小范围为0到24,M的大小范围为0到59(在0.7.9和0.6.34可用)。
一个非负的时间值将Cache-Control头设置为 max-age = #,#将适当的换算为秒数。
注意:expires仅仅适用于200, 204, 301, 302,和304应答
虽然上述的使用方式很多,经常使用的配置如下:
server { listen 2014; server_name localhost; location / { root html; } #告知浏览器缓存此文件并设置缓存时间 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 10s;#缓存2秒 #expires 2m;#缓存2分钟 #expires 2h;#缓存2小时 #expires 2d;#缓存2天 root html; } error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }
通过测试我们可以看到二次访问加载时间为0秒;响应上显示缓存时间为10秒,达到要求
4、压缩
场景:一些项目静态资源如html、css、js等都很多且很大,请求起来很费时间及流量,但这些资源往往都可以进行压缩,并且压缩比例很大;
解决方案:nginx使用gzip可指定类型进行压缩
gzip
语法:gzip on|off
默认值:gzip off
使用字段:http, server, location, location中的if字段
指定是否启用gzip压缩。
经常搭配下面使用:
gzip_types:默认值为gzip_types text/html ;为除“text/html”之外的MIME类型启用压缩,“text/html”总是会被压缩。
gzip_min_length:默认值为gzip_min_length 0 ;设置被压缩的最小请求,单位为bytes。少于这个值大小的请求将不会被压缩,这个值由请求头中的Content-Length字段决定。
gzip_buffers :默认值为gzip_buffers 4 4k/8k ;指定缓存压缩应答的缓冲区数量和大小,如果不设置,一个缓存区的大小为分页大小,根据环境的不同可能是4k或8k。
gzip_comp_level :默认值为gzip_comp_level 1 ;指定压缩等级,其值从1到9,1为最小化压缩(处理速度快),9为最大化压缩(处理速度慢)。
实例如下:
server { listen 2015; server_name localhost; location / { # 对js、css、html格式的文件启用gzip压缩功能,图片格式由于压缩比例太小,且压缩耗费cpu不建议压缩 gzip on; # 启用gzip压缩,默认是off,不启用 gzip_types application/javascript text/css;#为除“text/html”之外的MIME类型启用压缩,“text/html”总是会被压缩。 gzip_min_length 1024; # 所压缩文件的最小值,小于这个的不会压缩 gzip_buffers 4 1k; # 设置压缩响应的缓冲块的大小和个数,默认是内存一个页的大小 gzip_comp_level 1; # 压缩水平,默认1。取值范围1-9,取值越大压缩比率越大,但越耗cpu时间 root html; } error_page 500 502 503 504 /50x.html; location /50x.html { root html; } }
通过测试:js能够达到很好的压缩
总结:由于图片压缩率不高,如果进行压缩每次还要消耗资源如cpu等,得不偿失,不建议压缩图片;
原文:https://blog.csdn.net/u010904188/article/details/86487735