Nginx Rewrite相关功能

Nginx服务器利用ngx_http_rewrite_module模块解析和处理rewrite请求。rewrite用于实现URL的重写,类似于重定向功能,可以将用户的请求重写至别的目录,另外还可以在一定程度上提高网站的安全性。

- 5.1:ngx_http_rewrite_module模块命令

https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

- 5.1.1:if指令

用于条件匹配判断,根据条件判断结果选择不同的nginx配置,在server或location中配置。nginx的if语法只能支持单次判断,不支持多重判断,用法如下

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,变量与表达式之间可以用符号链接:

=  #比较变量与字符串是否相等
~  #表示在匹配过程中区分大小写字符
~* #表示在匹配过程中不区分大小写
-f 和 !-f #判断请求的文件存在与不存在
-d 和 !-d #判断请求的目录存在与不存在
-x 和 !-x #判断文件是否可执行
-e 和 !-e #判断请求的文件或目录是否存在(包括文件,目录,软链接)

注:若$变量的值为空或以0开头,则if指令认为此条件为false,其它条件为true

- 5.1.2 :set指令

指定key并给其定义一个变量,定义格式为set $key value,只有将内置变量赋值给自定义变量时无论是key还是value都要加$符号

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

- 5.1.3:break指令

用于中断当前相同作用域(location)中的其他配置,停止向下寻找,回到上一层作用域继续向下读取配置,该指令可在server块和location块以及ig块中使用,语法如下:

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,不再向下执行

- 5.1.4:return指令

return用于完成队请求的处理,并直接向客户端返回响应状态码处于此指令后的所有配置都将不被执行,return可以在server、if和location块进行配置,语法如下

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

- 5.1.5:rewrite_log 指令

设置是否开启记录ngx_http_rewrite_module模块日志记录到error_log日志文件中,可以配置在http、server、location或if当中,需要日志级别为notice

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

- 5.2:rewrite指令

通过正则表达式的匹配俩改变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

- 5.2.1:rewrite flag使用介绍

利用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           #日志处理

- 5.2.2:rewrite案例-域名永久与临时重定向

要求:因业务需要,将访问原域名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解析记录

- 5.2.3:rewrite案例-URI重定向

要求:访问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

- 5.2.4:rewrite案例-自动跳转https

要求:基于通信安全考虑公司网站要求全站https,所以要求将在不影响用户请求的情况下将http请求全部自动跳转至https,另外也可以实现部分location跳转

location / {
    root /data/html;
    index index.html;
    if ( $scheme = http ){ #未加条件判断,会陷入死循环
        rewrite / https://www.alijiujiu.com permanent;
    }
}

- 5.2.5:rewrite案例-判断文件是否存在

要求:当用户访问公司输入错误的URL,可以将用户重定向到公司首页

location / {
    root /data/html;
    index index.html;
    if ( !-f $request_filename ){
        #return 404 "input error";
        rewrite (.*) http://www.alijiujiu.com/index.html;
    }
}

- 5.3:Nginx防盗链

防盗链基于客户端携带的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并访问测试
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章