阅读目录html
一:理解地址重写 与 地址转发的含义。node
地址重写与地址转发是两个不一样的概念。nginx
地址重写 是为了实现地址的标准化,好比咱们能够在地址栏中中输入 www.baidu.com. 咱们也能够输入 www.baidu.cn. 最后都会被重写到 www.baidu.com 上。浏览器的地址栏也会显示www.baidu.com。正则表达式
地址转发:它是指在网络数据传输过程当中数据分组到达路由器或桥接器后,该设备经过检查分组地址并将数据转发到最近的局域网的过程。后端
所以地址重写和地址转发有如下不一样点:浏览器
1. 地址重写会改变浏览器中的地址,使之变成重写成浏览器最新的地址。而地址转发他是不会改变浏览器的地址的。
2. 地址重写会产生两次请求,而地址转发只会有一次请求。
3. 地址转发通常发生在同一站点项目内部,而地址重写且不受限制。
4. 地址转发的速度比地址重定向快。安全
二:理解 Rewrite指令 使用服务器
该指令是经过正则表达式的使用来改变URI。能够同时存在一个或多个指令。须要按照顺序依次对URL进行匹配和处理。cookie
该指令能够在server块或location块中配置,其基本语法结构以下:网络
rewrite regex replacement [flag];
rewrite的含义:该指令是实现URL重写的指令。
regex的含义:用于匹配URI的正则表达式。
replacement:将regex正则匹配到的内容替换成 replacement。
flag: flag标记。
flag有以下值:
last: 本条规则匹配完成后,继续向下匹配新的location URI 规则。(不经常使用)
break: 本条规则匹配完成即终止,再也不匹配后面的任何规则(不经常使用)。
redirect: 返回302临时重定向,浏览器地址会显示跳转新的URL地址。
permanent: 返回301永久重定向。浏览器地址会显示跳转新的URL地址。
好比以下列子:
rewrite ^/(.*) http://www.baidu.com/$1 permanent;
说明:
rewrite 为固定关键字,表示开始进行rewrite匹配规则。
regex 为 ^/(.*)。 这是一个正则表达式,匹配完整的域名和后面的路径地址。
replacement就是 http://www.baidu.com/$1 这块了,其中$1是取regex部分()里面的内容。若是匹配成功后跳转到的URL。
flag 就是 permanent,表明永久重定向的含义,即跳转到 http://www.baidu.com/$1 地址上。
下面咱们来作个简单的demo来模拟下:
1. 在咱们的测试项目下有个app.js. 代码以下:
const Koa = require('koa'); const app = new Koa(); const router = require('koa-router')(); // 添加路由 router.get('/', ctx => { ctx.body = '<h1>欢迎光临index page 页面</h1>'; }); router.get('/home', ctx => { ctx.body = '<h1>欢迎光临home页面</h1>'; }); router.get('/404', ctx => { ctx.body = '<h1>404...</h1>' }); // 加载路由中间件 app.use(router.routes()); app.listen(3001, () => { console.log('server is running at http://localhost:3001'); });
而后在命令行中 运行 node app.js 后,运行,咱们就能够在浏览器中 访问 http://localhost:3001 就能够访问到咱们对应的页面了。可是如今我想把该node项目
部署到我本地的nginx服务器上。nginx安装请看我这篇文章 而后我想使用域名来访问咱们的项目,所以咱们须要在咱们的nginx.conf中配置一下:
cd /usr/local/etc/nginx
而后使用命令:sudo open /usr/local/etc/nginx/nginx.conf -a 'sublime text' 命令打开 nginx.conf 配置以下:
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 8081; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } server { listen 8088; server_name xxx.abc.com; location / { proxy_pass http://127.0.0.1:3001; rewrite ^/(.*) http://www.baidu.com permanent; } } }
如上代码,我监听端口号是8088,而后server_name 配置设置为 xxx.abc.com, 而后当咱们访问 http://xxx.abc.com:8088/的时候,会先反向代理到咱们的http://127.0.0.1:3001下的node对应的页面上来,反向代理完成后,会使用 rewrite 重定向百度页面去了。如上配置完成后,咱们须要重启下nginx服务器;使用命令:
而后当咱们在浏览器访问 http://xxx.abc.com:8088/ 的时候,会执行以下图所示,它会先对 http://xxx.abc.com:8088/ 进行永久重定向(301), 而后会访问百度(307),临时重定向到百度页面来,最终加载百度页面的地址;以下演示所示:
可是若是我把 permanent 改为 redirect 的话,好比nginx配置:rewrite ^/(.*) http://www.baidu.com redirect; 后,它就会变成302临时重定向了。以下所示:
三:理解if指令
该指令用来支持条件判断的,而且根据条件判断结果来选择不一样的nginx的配置,咱们能够在server块或location块中配置该指令,它的语法结构为:
if (condition) { // .... }
condition 是布尔值 true/false的含义。
Rewrite 指令可用的全局变量以下:
1. $args: 该变量中存放了请求URL中的请求指令。好比 http://127.0.0.1:3001?arg1=value1&arg2=value2 中的
"arg1=value1&arg2=value2"。
2. $content_length: 该变量中存放了请求头中的Content-length字段。
3. $content_type: 该变量中存放了请求头中的 Content-type字段。
4. $document_root: 该变量中存放了针对当前请求的根路径。
5. $document_uri: 该变量中存放了请求的当前URI, 可是不包括请求指令。好比 http://xxx.abc.com/home/1?arg1=value1&
arg2=value2; 中的 "/home/1"
6. $host: 变量中存放了请求的URL中的主机部分字段,好比http://xxx.abc.com:8080/home中的 xxx.abc.com.
7. $http_host: 该变量与$host惟一区别带有端口号:好比上面的是 xxx.abc.com:8080
8. $http_user_agent: 变量中存放客户端的代理信息。
9. $http_cookie, 该变量中存放客户端的cookie信息。
10. $remote_addr 该变量中存放客户端的地址。
11. $remote_port 该变量中存放了客户端与服务器创建链接的端口号。
12. $remote_user 变量中存放客户端的用户名。
13. $request_body_file 变量中存放了发给后端服务器的本地文件资源的名称
14. $request_method 变量中存放了客户端的请求方式,好比 'GET'、'POST'等。
15. $request_filename 变量中存放了当前请求的资源文件的路径名。
16. $request_uri 变量中存放了当前请求的URI,而且带请求指令。
17. $query_string 和变量$args含义同样。
18. $scheme 变量中存放了客户端请求使用的协议,好比 'http', 'https'等。
19. $server_protocol 变量中存放了客户端请求协议的版本, 好比 'HTTP/1.0'、'HTTP/1.1' 等。
..... 等等
正则表达式的基本语法:
1. 对变量进行匹配
'~' 表示匹配过程当中对大小写敏感。
'~*' 表示匹配过程当中对大小写不敏感。
'!~' 若是 '~' 匹配失败时,那么该条件就为true。
'!~*' 若是 '~*' 匹配失败时,那么该条件就为true。
好比以下:
if ($http_user_agent ~ MSIE) { // 代码的含义:$http_user_agent值中是否含有 MSIE 字符串,若是包含为true,不然为false }
2. 判断请求的文件是否存在
'-f' 若是请求的文件存在,那么该条件为true。
'!-f' 若是该文件的目录存在,该文件不存在,那么返回true。若是该文件和目录都不存在,则为false。
若是请求的目录不存在,请求的文件存在,也为false。
if (-f $request_filename) { // 判断请求的文件是否存在 } if (!-f $request_filename) { // 判断请求的文件是否不存在 }
3. 判断请求的目录是否存在使用 '-d' 和 '!-d'
使用 '-d',若是请求的目录存在,则返回true。不然返回false。
使用 '!-d', 若是请求的目录不存在,可是该请求的上级目录存在,则返回true。若是该上级目录不存在,则返回false.... 等等其余一些语法,很少介绍。
如今咱们使用if指令来对nginx加一些判断;好比说咱们访问http://xxx.abc.com:8080/home时候,若是$host = 'xxx.abc.com' 的时候,就作重定向跳转,nginx配置代码以下:
server { listen 8088; server_name xxx.abc.com; location / { proxy_pass http://127.0.0.1:3001; if ($host = 'xxx.abc.com') { rewrite ^/(.*) http://www.cnblogs.com redirect; } } }
nginx 如上配置,若是咱们访问 http://xxx.abc.com:8088 的时候,它就会重定向到 http://www.cnblogs.com 来了。
好比更多的判断,好比若是用户代理是手机访问的话,直接跳转到某个页面去,也可使用if判断。好比以下:
if ( $http_user_agent ~* "(Android)|(iPhone)|(Mobile)|(WAP)|(UCWEB)" ){ rewrite ^/$ http://www.cnblogs.com permanent; }
四:理解防盗链及nginx配置
什么是防盗链?盗链能够理解盗图连接,也就是说把别人的图片偷过来用在本身的服务器上,那么防盗链能够理解为防止其余人把个人图片盗取过去。
防盗链的实现原理:客户端向服务器端请求资源时,为了减小网络带宽,提升响应时间,服务器通常不会一次将全部资源完整地传回客户端。好比请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器在解析文本的过程当中发现有图片存在时,会再次向服务器发起对该图片资源的请求,服务器将存储的图片资源再发送给客户端。可是若是这个图片是连接到其余站点的服务器上去了呢,好比在我项目中,我引用了的是淘宝中的一张图片的话,那么当咱们网站从新加载的时候,就会请求淘宝的服务器,那么这就颇有可能形成淘宝服务器负担。所以这个就是盗链行为。所以咱们要实现防盗链。
实现防盗链:使用http协议中请求头部的Referer头域来判断当前访问的网页或文件的源地址。经过该头域的值,咱们能够检测访问目标资源的源地址。若是目标源地址不是咱们本身站内的URL的话,那么这种状况下,咱们采起阻止措施,实现防盗链。可是注意的是:Referer头域中的值是能够被更改的。所以该方法也不能彻底安全阻止防盗链。
使用Nginx服务器的Rewrite功能实现防盗链。
Nginx中有一个指令 valid_referers. 该指令能够用来获取 Referer 头域中的值,而且根据该值的状况给 Nginx全局变量 $invalid_referer 赋值。若是Referer头域中没有符合 valid_referers指令的值的话,$invalid_referer变量将会赋值为1. valid_referers 指令基本语法以下:
valid_referers none | blocked | server_names | string
none: 检测Referer头域不存在的状况。
blocked: 检测Referer头域的值被防火墙或者代理服务器删除或假装的状况。那么在这种状况下,该头域的值不以"http://" 或 "https://" 开头。
server_names: 设置一个或多个URL,检测Referer头域的值是不是URL中的某个。
所以咱们有了 valid_referers指令和$invalid_referer变量的话,咱们就能够经过 Rewrite功能来实现防盗链。
下面咱们介绍两种方案:第一:根据请求资源的类型。第二:根据请求目录。
1. 根据请求文件类型实现防盗链配置实列以下:
server { listen 8080; server_name xxx.abc.com location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ { valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com; if ($invalid_referer) { rewrite ^/ http://www.xxx.com/images/forbidden.png; } } }
如上基本配置,当有网络链接对以 gif、jpg、png为后缀的图片资源时候、当有以swf、flv为后缀的媒体资源时、或以 rar、zip为后缀的压缩资源发起请求时,若是检测到Referer头域中没有符合 valid_referers指令的话,那么说明不是本站的资源请求。
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ 该配置的含义是 设置防盗链的文件类型。
valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com; 能够理解为白名单,容许文件链出的域名白名单,若是请求的资源文件不是以这些域名开头的话,就说明请求的资源文件不是该域下的请求,所以能够判断它是盗链。所以若是不是该域下的请求,就会使用 Rewrite进行重定向到 http://www.xxx.com/images/forbidden.png 这个图片,好比这张图片是一个x或其余的标识,而后其余的网站就访问不了你这个图片哦。
2. 根据请求目录实现防盗链的配置实列以下:
server { listen 8080; server_name xxx.abc.com location /file/ { root /server/file/; valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com; if ($invalid_referer) { rewrite ^/ http://www.xxx.com/images/forbidden.png; } } }