Nginx服务器利用ngx_http_rewrite_module模块解析和处理rewrite请求。rewrite用于实现URL的重写,相似于重定向功能,能够将用户的请求重写至别的目录,另外还能够在必定程度上提升网站的安全性。html
https://nginx.org/en/docs/http/ngx_http_rewrite_module.htmllinux
用于条件匹配判断,根据条件判断结果选择不一样的nginx配置,在server或location中配置。nginx的if语法只能支持单次判断,不支持多重判断,用法以下nginx
if (条件匹配) { action } #示例1 location /main { index index.html; default_type text/html; if ( $scheme = http ){ echo "if ---> $scheme"; } if ($scheme = https ){ echo "if ---> $scheme"; } }
使用正则表达式对变量进行匹配,成功为true,不然false,变量与表达式之间能够用符号连接:web
= #比较变量与字符串是否相等 ~ #表示在匹配过程当中区分大小写字符 ~* #表示在匹配过程当中不区分大小写 -f 和 !-f #判断请求的文件存在与不存在 -d 和 !-d #判断请求的目录存在与不存在 -x 和 !-x #判断文件是否可执行 -e 和 !-e #判断请求的文件或目录是否存在(包括文件,目录,软连接)
注:若$变量的值为空或以0开头,则if指令认为此条件为false,其它条件为true正则表达式
指定key并给其定义一个变量,定义格式为set $key value,只有将内置变量赋值给自定义变量时不管是key仍是value都要加$符号express
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; set $my_port &server_port; echo $my_port; }
用于中断当前相同做用域(location)中的其余配置,中止向下寻找,回到上一层做用域继续向下读取配置,该指令可在server块和location块以及ig块中使用,语法以下:vim
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; break; set $my_port &server_port; echo $my_port; } #只输出$name的值javis,再也不向下执行
return用于完成队请求的处理,并直接向客户端返回响应状态码处于此指令后的全部配置都将不被执行,return能够在server、if和location块进行配置,语法以下centos
return code #返回给客户端指定的http状态码 return code (text) #返回给客户端指定的状态码及响应内容,能够调用变量 return code URL #返回给客户端的URL地址 示例1 location /main { root /data/html; index index.html; default_type text/html; if ( $scheme = http ){ return 500 "server error"; echo "if --->" $scheme; #只输出server error,后面的将不执行 } if ( $scheme = https){ echo "if --->" $scheme; } }
设置是否开启记录ngx_http_rewrite_module模块日志记录到error_log日志文件中,能够配置在http、server、location或if当中,须要日志级别为noticeapi
location /main { root /data/html; index index.html; default_type text/html; set $name javis; echo $name; rewrite_log on; break; set $my_port &server_port; echo $my_port; } #重启nginx,访问error_log
经过正则表达式的匹配俩改变URI,能够同时存在一个或多个指令,按照次序对URI进行匹配,rewrite主要是针对用户请求的URL或URI做具体处理浏览器
URI:通用资源标识符,标识一个资源的路径,能够不带协议 URL:统一资源定位符,用于在internet中描述资源的字符串,时URI的子集,主要包括传输协议(scheme)、主机(IP、端口号或者域名)和资源具体地址(目录和文件名)等三部分,通常格式为 scheme://主机名[:端口号][/资源路径],如:http://www.a.com:8080/path/file/index.html就是一个URL路径,URL必须带访问协议。 区别:每个URL都是URI,但URI不都是URL 示例: http://example.org/path/to/resource.txt #URI/URL ftp://example.org/resource.txt #URI/URL /absolute/path/to/resource.txt #URI
rewrite官方介绍:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite,能够配置在server、location、if中,语法以下:
rewrite regex replacement [flag];
rewrite将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为表达式指定的新的URI。若在同一级配置模块中存在多个rewrite规则,就会自上而下逐个检查;被某规格替换后,会从新一轮新的替换检查,隐含有循环机制,但不超过10次;若超过则提示500响应吗,[flag]所标识的标志位用于控制此循环机制,,若是替换后的URL是以http://或https://开头,则替换结果会以重定向返回客户端,即永久重定向301
利用nginx的rewrite的指令,能够实现url的从新跳转,rewrtie有四种不一样的flag,分别是redirect(临时重定向)、permanent(永久重定向)、break和last。其中前两种是跳转型的flag,后两种是代理型,跳转型是指有客户端浏览器从新对新地址进行请求,代理型是在WEB服务器内部实现跳转的。
redirect #临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,有客户端从新发起请求,使用相对路径,http://或https://开头,状态码:302 permanent #永久重定向,以永久重定向的方式直接返回重写后生成的新URL给客户端,由客户端从新发起新的请求,状态码:301 last #重写完成后中止对当前location中后续的其余重写操做,然后对新的URL启动新一轮重写检查,不建议在location中使用 break #重写完成后中止对当前URL在当前location中后续的其余重写操做,然后直接跳转至重写规则匹配块以后的其余配置;结束循环,建议在location中使用
这里应该了解nginx处理的十一个阶段
NGX_HTTP_POST_READ_PHASE = 0, #读取请求头 NGX_HTTP_SERVER_REWRITE_PHASE, #执行rewrite NGX_HTTP_FIND_CONFIG_PHASE, #根据uri替换location NGX_HTTP_REWRITE_PHASE, #根据替换结果继续执行rewrite NGX_HTTP_POST_REWRITE_PHASE, #执行rewrite后处理 NGX_HTTP_PREACCESS_PHASE, #认证预处理 请求限制,链接限制 NGX_HTTP_ACCESS_PHASE, #认证处理 NGX_HTTP_POST_ACCESS_PHASE, #认证后处理, 认证不经过, 丢包 NGX_HTTP_TRY_FILES_PHASE, #尝试try标签 NGX_HTTP_CONTENT_PHASE, #内容处理 NGX_HTTP_LOG_PHASE #日志处理
要求:因业务须要,将访问原域名www.linux.net的请求永久重定向到www.linux.com
临时重定向不会缓存域名解析记录(A记录),可是永久重定向会缓存
location / { root /data/html; index index.html; rewrite / http://www.linux.com permanent; #rewrite / http://www.linux.com redirect; }
(1)临时重定向:告诉浏览器域名不是固定重定向到当前目标域名,后期可能随时会更改,所以浏览器不会缓存当前域名的解析记录
(2)永久重定向:永久重定向会缓存DNS解析记录
要求:访问break的请求被转发至image,而访问last传递请求也被转发至image,以此测试last和break的区别
location /break { # root /data/html; rewrite ^/break/(.*) /test/$1 break;#重写后直接直接找test目录,若没有为此处的test指定根目录,则访问不到,换言之,若要成功跳转,test须要完整路径 return 666 "break"; } location /last { rewrite ^/last/(.*) /test/$1 last;#完成重写后,在全部location里面从新开始一轮遍历,进到test,访问成功 return 888 "last"; } location /test { return 999 "test"; }
重启nginx的访问测试
[root@centos ~]$curl -L -i www.alijiujiu.com/break/ #break不会跳转至location /test中 HTTP/1.1 404 Not Found Server: nginx/1.14.2 Date: Sat, 01 Jun 2019 06:14:27 GMT Content-Type: text/html Content-Length: 19 Connection: keep-alive Keep-Alive: timeout=10 ETag: "5cee850d-13" this is error page [root@centos ~]$curl -L -i www.alijiujiu.com/last/ #last会跳转至location /test中继续执行匹配操做 HTTP/1.1 999 Server: nginx/1.14.2 Date: Sat, 01 Jun 2019 06:14:46 GMT Content-Type: application/octet-stream Content-Length: 4 Connection: keep-alive Keep-Alive: timeout=10 test
要求:基于通讯安全考虑公司网站要求全站https,因此要求将在不影响用户请求的状况下将http请求所有自动跳转至https,另外也能够实现部分location跳转
location / { root /data/html; index index.html; if ( $scheme = http ){ #未加条件判断,会陷入死循环 rewrite / https://www.alijiujiu.com permanent; } }
要求:当用户访问公司输入错误的URL,能够将用户重定向到公司首页
location / { root /data/html; index index.html; if ( !-f $request_filename ){ #return 404 "input error"; rewrite (.*) http://www.alijiujiu.com/index.html; } }
防盗链基于客户端携带的referer实现,referer是记录打开一个页面以前记录是从哪一个页面跳转过来的标记信息,若是别人只连接了本身网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗链,referer就是以前的那个网站域名,正常的referer信息有如下几种
none:请求报文首部没有referer首部,好比用户直接在浏览器输入域名访问web网站,就没有referer信息。 blocked:请求报文有referer首部,但无有效值,好比为空。 server_names:referer首部中包含本主机名及即nginx 监听的server_name。 arbitrary_string:自定义指定字符串,但可以使用*做通配符。 regular expression:被指定的正则表达式模式匹配到的字符串,要使用~开头,例如:~.*\.magedu\.com。
5.3.1:实现防盗链
基于访问安全考虑,nginx支持经过ungx_http_referer_module模块 https://nginx.org/en/docs/http/ngx_http_referer_module.html#valid_referers 检查访问请求的referer信息是否有效实现防盗链功能,定义方式以下:
[root@centos ~]$vim /apps/nginx/conf/conf.d/pc.conf location /image { root /data/html/; index index.html; valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.; if ( $invalid_referer ){ return 403; } }
实现防盗链:
location ^~ /images { root /data/nginx; index index.html; valid_referers none blocked server_names *.alijiujiu.com www.alijiujiu.* api.online.test/v1/hostlist ~\.google\. ~\.baidu\.; #定义有效的referer if ($invalid_referer) { #假如是使用其余的无效的referer访问: return 403; #返回状态码403 } } #重启Nginx并访问测试