Nginx静态资源部署优化_缓存、跨域、防盗链03

静态资源缓存处理

web 缓存: 一个web资源存在于web服务器和客户端之间的副本

web缓存分类

1
2
3
4
客户端缓存
浏览器缓存 - 浏览器在用户磁盘上的资源缓存
服务端缓存
Nginx/Redis/Memcache等

浏览器缓存执行流程

HTTP协议中与页面缓存相关的字段:

headers 说明
Expires 缓存过期的日期时间
Cache-Control 设置缓存相关配置信息
Last-Modified 请求资源最后修改时间
ETag 请求实体标签的当前值, 如文件的MD5值

image-20211120005659396

1
2
强缓存: 直接从浏览器端使用缓存, 不与服务端交互
协商缓存: 发现本地缓存过期后, 发送请求与服务端协商, 服务端判定资源未发生变化, 返回304, 仍使用浏览器缓存

Nginx浏览器缓存指令

Nginx实现对应缓存设置, 需要如下指令

expires

用于控制页面资源过期时间, 可以通过控制HTTP响应头中的ExpiresCache-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;
}

image-20211120012032536

add_header

用于添加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>

请求结果如下:

image-20211120023920588

跨域解决方案

使用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;
}
}

重新请求结果如下:

image-20211120024917471

静态资源防盗链

资源盗链: 将不在自己服务器上的静态资源通过技术手段, 绕过限制放置到自己的页面上展示给用户, 依次盗取大网站的空间和流量

如下所示代码:

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;
}

效果展示

image-20211120042313902

通过模块精细化设置

需要使用Nginx模块 ngx_http_accesskey_module