静态资源缓存处理
web 缓存: 一个web资源存在于web服务器和客户端之间的副本
web缓存分类
1 2 3 4
| 客户端缓存 浏览器缓存 - 浏览器在用户磁盘上的资源缓存 服务端缓存 Nginx/Redis/Memcache等
|
浏览器缓存执行流程
HTTP协议中与页面缓存相关的字段:
| headers |
说明 |
| Expires |
缓存过期的日期时间 |
| Cache-Control |
设置缓存相关配置信息 |
| Last-Modified |
请求资源最后修改时间 |
| ETag |
请求实体标签的当前值, 如文件的MD5值 |

1 2
| 强缓存: 直接从浏览器端使用缓存, 不与服务端交互 协商缓存: 发现本地缓存过期后, 发送请求与服务端协商, 服务端判定资源未发生变化, 返回304, 仍使用浏览器缓存
|
Nginx浏览器缓存指令
Nginx实现对应缓存设置, 需要如下指令
expires
用于控制页面资源过期时间, 可以通过控制HTTP响应头中的Expires 和 Cache-Control 实现
指令格式
expires [modified] time; || expires epoch|max|off;
1 2 3 4 5 6 7 8
| time: 可以为任意整数指定过期时间, 单位为秒. 如果是负数, Cache-Control值设定为no-cache 如果为正数或0, 则Cache-Control被设定为max-age=time epoch: 指定Expires值为'1 January,1970,00:00:00 GMT', 即1970-01-01 00:00:00, Cache-Control值为no-cache max: 指定Expires值为'31December,2037,23:59:59 GMT', 即2037-12-31 23:59:59 Cache-Control值为315360000 (10年) off: 不缓存
|
注: HTTP响应头中, Expires和Cache-Control共同控制缓存过期配置.
其中, Expires为1.0版本协议, 使用GMT时间对照浏览器与服务器资源过期时间, 在时间配置不同步时会出现问题.
所以在1.1版本中, 使用Cache-Control:max-age=time, 以相对时间对照过期时间, 实现资源缓存的配置
指令配置
1 2 3
| location ~ .*\.(html|js|css|png)${ expires 1000; }
|

用于添加HTTP响应头信息, 值
指令语法
add_header name value [always];
1 2 3 4 5 6 7 8 9 10
| 其中缓存配置主要修改Cache-Control值, 值包括: must-revalidate 可缓存但必须向服务器进行确认协商 no-cache 指示请求或响应消息不能缓存,不是说可以设置不缓存,而是需要和服务器确认 no-store 不缓存请求或响应的任何内容 no-transform 代理不可更改媒体类型 public 可向任意方提供响应缓存 private 可向特定用户提供响应缓存 proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再次确认 max-age=<seconds> 最大响应缓存Age时间 s-maxage=<seconds> 公共缓存服务器响应的最大Age值
|
指令配置
1 2 3
| location ~ .*\.(html|js|css|png)${ add_header Cache-Control no-store; }
|
Nginx跨域问题解决
浏览器同源策略
浏览器的一种约定策略, 将协议、域名(IP)、端口相同的请求称为同源请求.
跨域问题
即存在两台服务器A, B. 如果从A的页面发送异步请求到B获取数据, 如果服务器A和B不满足同源策略, 就会出现跨域问题
跨域演示
新建nginx配置server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| server { listen 8081; server_name test.project.com; location / { root /var/www/test; index index.html; } } server { listen 8082; server_name localhost; location / { root /var/www/test/another; index index.html index.php; } }
|
新建/var/www/test/index.html文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>跨域演示</title> <script src="jquery.js"></script> </head> <body> <input type="button" name="bt" value="获取跨域数据" id="btn"> </body> <script type="text/javascript"> $(function(){ $("#btn").click(function(){ $.get('http://192.168.253.134:8082/getUser', function(data){ alert(JSON.stringify(data)); }) }); }); </script> </html>
|
请求结果如下:

跨域解决方案
使用Nginx指令add_header 添加响应头信息
1 2 3
| 需要添加两个信息: Access-Control-Allow-Origin # 允许访问域名, 可配置多个,逗号分隔, 或 * 代表所有 Access-Control-Allow-Methods # 允许访问方式, 可配置多个,逗号分隔
|
如修改上述案例的nginx配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| server { listen 8081; server_name test.project.com; location / { root /var/www/test; index index.html; } } server { listen 8082; server_name localhost; location / { add_header Access-Control-Allow-Origin http://test.project.com:8081; add_header Access-Control-Allow-Methods *; root /var/www/test/another; index index.html index.php; } }
|
重新请求结果如下:

静态资源防盗链
资源盗链: 将不在自己服务器上的静态资源通过技术手段, 绕过限制放置到自己的页面上展示给用户, 依次盗取大网站的空间和流量
如下所示代码:
1 2 3 4 5 6 7 8 9 10
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>盗链演示</title> </head> <body> <img src="https://m.360buyimg.com/babel/jfs/t1/169821/25/23076/279367/6191c359E738f3e96/64e56f4355e3cd20.gif"> </body> </html>
|
实现原理
使用HTTP请求头中的Referer , 获取来源网站地址是否为信任地址, 若是则放行访问, 若不是则返回403(拒绝访问)状态码
使用Nginx指令valid_referers 实现匹配
指令格式
valid_referers none|blocked|server_names|string ...
1
| 指令valid_referers会通过匹配Referer和配置后面的内容, 将结果赋给变量$invalid_referer, 若匹配成功, 该值等于0, 匹配失败, 该值等于1, 匹配时不区分大小写
|
1 2 3 4
| none: 如果Header中的Referer为空, 允许访问 blocker: Header中的Referer不为空, 但该值被防火墙或代理伪装过, 如不带http:// https://等协议头, 允许访问 server_names: 具体的域名或IP string: 支持正则表达式和*的统配符表达式如: *.example.com ~.*\.google\..*
|
Nginx配置实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| location ~ ^.*\.(png|jpg|gif)$ { valid_referers none blocked www.baidu.com; if ($invalid_referer) { return 403; } }
location /images { valid_referers none blocked www.baidu.com; if ($invalid_referer) { return 403; } root /var/www/test; }
|
效果展示

通过模块精细化设置
需要使用Nginx模块 ngx_http_accesskey_module