Nginx rewrite地址重写(十个例子详细解析)

Nginx rewrite地址重写

  • [1. 什么是 Rewrite](#1. 什么是 Rewrite)
  • [2. Rewrite 相关指令](#2. Rewrite 相关指令)
    • [2.1. if 语句](#2.1. if 语句)
    • [2.2. Rewrite flag](#2.2. Rewrite flag)
    • [2.3. permanent 匹配示例](#2.3. permanent 匹配示例)
    • [2.4. set 指令](#2.4. set 指令)
    • [2.5. return 指令](#2.5. return 指令)
    • [2.6. last、break详解](#2.6. last、break详解)
    • [2.7. Nginx https rewrite(扩展)](#2.7. Nginx https rewrite(扩展))

1. 什么是 Rewrite

Rewrite在nginx中也叫URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程

从安全角度考虑,使用Rewrite在Nginx中具有一些重要的作用和优势,包括:

  1. 隐藏真实目录结构:
  • 使用Rewrite可以隐藏服务器上的真实文件路径和目录结构,防止攻击者通过直接访问文件路径来获取敏感信息。这增加了安全性,使攻击者更难确定服务器上的实际文件组织方式。
  1. 规范化URL:
  • 强制规范化URL格式可以避免一些常见的安全问题,如路径遍历攻击(Directory Traversal)或路径参数欺骗。通过使用Rewrite,可以确保URL格式的一致性,减少潜在的安全漏洞。
  1. 防止盗链:
  • 通过Rewrite可以实施防盗链策略,防止其他网站直接链接到本站的资源。这有助于减轻服务器负载,防止不法分子盗用网站的带宽,并提高资源的安全性。
  1. HTTP到HTTPS的强制重定向:
  • 通过Rewrite可以实现将HTTP请求强制重定向到HTTPS,确保数据在传输过程中的安全性。这是保障通信安全的一种有效手段,尤其对于涉及用户敏感信息的网站至关重要。
  1. 条件性重写:
  • 可以根据请求中的条件来选择是否进行重写,例如,只有特定IP范围的请求才允许进行某种操作。这有助于实现访问控制和强化安全性。
  1. 跨站点脚本(XSS)防护:
  • 通过Rewrite可以对请求参数进行过滤或修改,防止恶意用户通过注入脚本来进行XSS攻击。对URL和参数进行适当的重写可以减轻XSS攻击的风险。
  1. 统一资源标识符(URI)规范化:
  • 通过强制规范化URI,可以防止攻击者尝试混淆或绕过安全策略。规范化的URI有助于提高应用程序的安全性,防范一些常见的攻击手法。
  1. 避免敏感信息泄露:
  • 通过Rewrite可以限制对某些敏感信息或文件的访问,确保只有授权用户能够获取特定内容。这有助于防止敏感信息泄露和未授权访问。

2. Rewrite 相关指令

  • Nginx Rewrite 相关指令有 ifrewritesetreturn

2.1. if 语句

应用环境:server,location

语法:

bash 复制代码
if (condition) { ... }

if 可以支持如下条件判断匹配符号
~             正则匹配 (区分大小写)
~*            正则匹配 (不区分大小写)
!~            正则不匹配 (区分大小写)
!~*           正则不匹配  (不区分大小写)
-f 和!-f      用来判断是否存在文件
-d 和!-d      用来判断是否存在目录
-e 和!-e      用来判断是否存在文件或目录
-x 和!-x      用来判断文件是否可执行

#在匹配过程中可以引用一些Nginx的全局变量
$args            	请求中的参数;
$document_root      针对当前请求的根路径设置值;
$host            	请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate        	对连接速率的限制;
$request_method     请求的方法,比如"GET"、"POST"等;
$remote_addr        客户端地址;
$remote_port        客户端端口号;
$remote_user        客户端用户名,认证用;
$request_filename   当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images/a.jpg)
$request_uri        用于表示客户端请求的完整 URI,也就是请求地址,它记录了客户端发起的请求地址
$query_string       与$args相同;
$scheme             用的协议,比如http或者是https
$server_protocol    请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr        服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name        请求到达的服务器名;
$document_uri       与$uri一样,URI地址;
$server_port        请求到达的服务器端口号;

2.2. Rewrite flag

rewrite 指令根据表达式来重定向URI,或者修改字符串。可以应用于server、ocation、if 环境下,每行rewrite指令最后跟一个flag标记

支持的flag标记有:

bash 复制代码
last         相当于Apache里的[L]标记,表示完成rewrite。默认为last。
 			(last标记位的location,永远匹配不上,相当于这个location备注掉了)
break        本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect     返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent    返回301永久重定向,浏览器地址会显示跳转后URL地址

redirect 和 permanent 区别是返回的不同方式的重定向

  • 对于客户端来说一般状态下是没有区别的。
  • 而对于搜索引擎,相对来说301的重定向更加友好,如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。
  • 使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会发生更改。

2.3. permanent 匹配示例

所有例子都记得要修改本地解析host文件

例1:http://www.testpm.com/a/1.html ------> http://www.testpm.com/b/2.html

c 复制代码
[root@localhost ~]# mkdir /html
[root@localhost ~]# cd /html/
[root@localhost html]# mkdir a b
[root@localhost html]# ls
a  b
[root@localhost html]# cd a/
[root@localhost a]# echo "this is a" >1.html
[root@localhost a]# cd ../b
[root@localhost b]# echo "this is b" >2.html​
[root@localhost b]# cd /etc/nginx/conf.d/
[root@localhost conf.d]# vim ab.conf
server {
    listen 80; 
    server_name www.testpm.com;
    
      location /a {
          root /html;
          index   1.html index.htm;
          rewrite .* /b/2.html permanent;
          }
​
      location /b {
          root    /html;
          index   2.html index.htm;
          }
}
[root@localhost conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost conf.d]# systemctl restart nginx
​
//本地windows做好host文件的解析
C:\Windows\System32\drivers\etc\hosts
192.168.221.136 www.testpm.com
//浏览器访问:
访问 http://www.testpm.com/a  会跳转到------> http://www.testpm.com/b/2.html

​例2:http://www.testpm.com/2019/a/1.html ==> http://www.testpm.com/2018/a/1.html

c 复制代码
[root@localhost ~]# mkdir /var/www/html -p
[root@localhost html]# pwd
/var/www/html 
[root@localhost html]# ls
2018  2019
[root@localhost html]# mkdir 2018/a
[root@localhost html]# mkdir 2019/a
[root@localhost html]# echo "2018" > 2018/a/1.html
[root@localhost html]# echo "2019" > 2019/a/1.html
[root@localhost conf.d]# vim 20182019.conf
server {
    listen       80;
    server_name  www.erling.com;
​
    location /2019/a {
        root    /var/www/html;
        index   1.html index.htm;
        rewrite ^/2019/(.*)$ /2018/$1 permanent;    #(.*)$以任意结尾;$1就是前面的(.*)位置参数
        }
​
    location /2018/a {
        root    /var/www/html;
        index   1.html index.htm;
        }
}
[root@localhost conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost conf.d]# systemctl restart nginx
//本地host文件添加解析
192.168.221.136 www.erling.com
​//浏览器访问:
访问 http://www.erling.com/2019/a 会跳转到------> http://www.erling.com/2018/a/

​例3:http://www.xf.com ==> http://jd.com

c 复制代码
[root@localhost conf.d]# vim xf-jd.conf
server{
        listen 80;
        server_name www.xf.com;
​
        location / {
        root /html;
        if ($host ~* www.xf.com) {
                rewrite .* https://www.jd.com permanent;
                #永久重定向到jd.com
                }
        }
}
​
参数解释:
$host ~* www.xf.com     $主机名,~*正则匹配不区分大小写

//本地host文件添加解析
192.168.221.136 www.xf.com
​//浏览器访问
访问 www.xf.com 会跳转到------> https://www.jd.com/

例4:http://www.xf-html.com/a/1.html ==> http://jd.com/a/1.html

c 复制代码
[root@localhost conf.d]# cp xf-jd.conf xf-html-jd.conf
[root@localhost conf.d]# vim xf-html-jd.conf 
server{
        listen 80;
        server_name www.xf-html.com;
​
        location /a {
        root /html;
        index 1.html index.htm;
        if ($host ~* www.xf-html.com) {
                rewrite .* https://www.jd.com$request_uri permanent;
                }
        }
}
//本地host文件添加解析
192.168.221.136 www.xf-html.com
​//浏览器访问
访问 www.xf-html.com/a/1.html 会跳转到------> https://www.jd.com/a/1.html(由于该页面没有,所以会跳转到https://www.jd.com/error2.aspx)

例5: 在访问目录后添加/ (如果目录后已有/,则不加/)

c 复制代码
[root@localhost conf.d]# mkdir -p /usr/share/nginx/html/a/b/c
[root@localhost conf.d]# cp /usr/share/nginx/html/index.html  /usr/share/nginx/html/a/b/c/
[root@localhost conf.d]# vim root.conf
server {
        listen 80;
        server_name www.xfroot.com;
​
        location /a/b/c {
        root /usr/share/nginx/html;
        index index.html index.htm;
        if (-d request_filename) {  #判断目录
           rewrite ^(.*)([^/])$  http://$1$2/ permanent;    #以任意字符开头,不以/结尾------>跳转到前面一样的路径,但是在最后加上/
                }
        }
}

参数解释:
http://www.xf.com/a/b/c
$1: /a/b/
$2: c
http://$host$1$2/
​
[root@localhost conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost conf.d]# systemctl restart nginx
​//本地host文件添加解析
192.168.221.136 www.xfroot.com
​//浏览器访问
访问 http://www.xfroot.com/a/b/c 会跳转到------> http://www.xfroot.com/a/b/c/

例6:重定向后,在最后添加一个user=

http://www.xf.com/login/xf.html ==> http://www.xf.com/reg/login.html?user=xf

c 复制代码
[root@localhost conf.d]# vim user.conf 
server{
        listen 80;
        server_name www.xfuser.com;
​
        location /login{    #匹配到login
        root /usr/share/nginx/html; 
        index index.html index.htm;
        rewrite ^/login/(.*)\.html$ http://$host/reg/login.html?user=$1;    #以login开头的,以任意字符串.html结尾的  重定向到http://前面的主机名/reg/login.html?user=主机名,$1是一个位置参数
        }
​
        location /reg{      #匹配reg
        root /usr/share/nginx/html;
        index login.html index.htm;
        }
}
[root@localhost html]# pwd
/usr/share/nginx/html        
[root@localhost html]# mkdir reg
[root@localhost html]# echo "login" > reg/login.html        
[root@localhost html]# mkdir login
[root@localhost html]# cp index.html  login/        
//本地host文件添加解析
192.168.221.136 www.xfuser.com
​//浏览器访问
访问 http://www.xfuser.com/login/index.html 会跳转到------> http://www.xfuser.com/reg/login.html?user=index

user=1,1对应的是index,为什么是index而不是login呢?

因为:$1匹配的是正则中的第一个子匹配部分

^/login/ 匹配/login/

(.*) 匹配index

.html$ 匹配.html

$1是匹配正则中第一个子匹配的,所以就是index

例7:数字重定向成 数字/

http://www.xf.com/xf/11-22-33/1.html ==> http://www.xf.com/xf/11/22/33/1.html

c 复制代码
[root@localhost conf.d]# pwd
/etc/nginx/conf.d
[root@localhost conf.d]# vim int.conf 
server {
        listen 80;
        server_name www.xfint.com;
​
        location /xf{
        root /html;
        rewrite ^/xf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$  /xf/$1/$2/$3$4 permanent;
        //匹配以xf开头/0-9出现一个或者多个,匹配三次,最后以任意字符结尾 ------>永久重定向到/xf开头/前面的1234位置参数,因为前面的.*已经包含了/所以重定向的时候就不用写/了
        }
​
        location /xf/11/22/33{
        root /html;
        index 1.html index.htm;
        }
}
[root@localhost html]# cd /html/
[root@localhost html]# mkdir  -p  xf/11/22/33      
[root@localhost html]# echo "hello world" > xf/11/22/33/1.html
​//本地host文件添加解析
192.168.221.136 www.xfint.com
​//浏览器访问
访问 www.xfint.com/xf/11-22-33/1.html 会跳转到 http://www.xfint.com/xf/11/22/33/1.html最终显示hello world

2.4. set 指令

set 指令是用于定义一个变量,并且赋值

应用范围:server、location、if

应用示例

例8:http://alice.testpm.com ==> http://www.testpm.com/alice

http://jack.testpm.com ==> http://www.testpm.com/jack

c 复制代码
[root@localhost conf.d]# cd /usr/share/nginx/html/
[root@localhost html]# mkdir jack alice
[root@localhost html]# echo "jack.." >> jack/index.html
[root@localhost html]# echo "alice.." >> alice/index.html
​
​//编辑配置文件:
[root@localhost conf.d]# vim alice_jack.conf
server {
    listen       80;
    server_name  www.testpm.com;
​
    location / {
         root   /usr/share/nginx/html;
         index  index.html index.htm;
         if ( $host ~* ^www.testpm.com$) {
                break;
                }
         if ( $host ~* "^(.*)\.testpm\.com$" ) {
                set $user $1;
                rewrite .* http://www.testpm.com/$user permanent;
                }
        }
    location /jack {
         root /usr/share/nginx/html;
         index  index.html index.hml;
        }
    location /alice {
         root /usr/share/nginx/html;
         index index.html index.hml;
        }
}
[root@localhost conf.d]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@localhost conf.d]# systemctl restart nginx
​
本地host文件添加解析
192.168.221.136 www.testpm.com
192.168.221.136 jack.testpm.com
192.168.221.136 alice.testpm.com
​
浏览器访问
访问www.testpm.com时,会出现nginx的欢迎界面
访问 jack.testpm.com 会跳转到 http://www.testom.com/jack
访问 alice.testpm.com 会跳转到 http://www.testom.com/alice

2.5. return 指令

return 指令用于返回状态码给客户端

应用范围:server、location、if

应用示例:

例9:如果访问的.sh结尾的文件则返回403操作拒绝错误

c 复制代码
[root@localhost conf.d]# vim return.conf 
server {
    listen       80;
    server_name  www.testpmxf.cn;
    #access_log  /var/log/nginx/http_access.log  main;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        }
    location ~* \.sh$ {
        return 403;
        }
}
​//本地host文件添加解析
192.168.221.136 www.testpmxf.cn
​//浏览器访问
http://www.testpmxf.cn/test.sh 会报403 Forbidden

例10:80端口 转 443端口(需要有ssl证书才能行)​

bash 复制代码
server {
    listen       80;
    server_name  www.testpm.cn;
    access_log  /var/log/nginx/http_access.log  main;
    return 301 https://www.testpm.cn$request_uri;   #返回301永久重定向
}
server {
    listen 443 ssl;
    server_name www.testpm.cn;
    access_log  /var/log/nginx/https_access.log  main;
​
    #ssl on;
    ssl_certificate   /etc/nginx/cert/2447549_www.testpm.cn.pem;
    ssl_certificate_key  /etc/nginx/cert/2447549_www.testpm.cn.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers on;
​
    location / {
        root  /usr/share/nginx/html;
        index index.html index.htm;
    }
}
c 复制代码
[root@localhost ~]# curl -I http://www.testpm.cn
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.0
Date: Wed, 03 Jul 2019 13:52:30 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
Location: https://www.testpm.cn/

2.6. last、break详解

  • last:停止匹配当前所在的location,继续匹配下一组location。
  • break:终止nginx在当前请求中的所有location的匹配,直接使用当前location的配置当作最终的处理请求,不会继续往下进行匹配。
  • ​使用 proxy_pass 指令时,尽量使用break
c 复制代码
[root@localhost ~]# vim /etc/nginx/conf.d/last_break.conf 
server {
    listen       80;
    server_name  www.testlast_break.com;
    access_log  /var/log/nginx/last.access.log  main;
​
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    location /break/ {
        root /usr/share/nginx/html;
        rewrite .* /test/break.html break;
    }
    location /last/ {
        root /usr/share/nginx/html;
        rewrite .* /test/last.html last;
    }
    location /test/ {
        root /usr/share/nginx/html;
        rewrite .* /test/test.html break;
    }
}
[root@localhost ~]# cd /usr/share/nginx/html/
[root@localhost html]# mkdir last  break test
[root@localhost html]# echo "last" > test/last.html
[root@localhost html]# echo "break" > test/break.html
[root@localhost html]# echo "test" > test/test.html

浏览器访问

http://www.testlast_break.com/break/ ------> 会被重定向到break.html,会显示break

http://www.testlast_break.com/last/ ------> 会被重定向到last.html,跳出本个location匹配,匹配下一组location,所以最终会显示test

http://www.testlast_break.com/test/ ------> 会被重定向到test.html,显示test,然后终止后续的匹配

拓展:当last后面没有location资源匹配时,会last自己location的资源进行匹配,也就是会访问到http://www.testlast_break.com/last/last.index;可以将实验中test的location资源注释掉验证效果。

2.7. Nginx https rewrite(扩展)

(证书购买官网有标准配置教程)

bash 复制代码
server {
        listen       80;
        server_name  *.vip9999.top vip9999.top;
        if ($host ~* "^www.vip9999.top$|^vip9999.top$" ) {
                return 301 https://www.vip9999.top$request_uri;
        }
    }
​
    # Settings for a TLS enabled server.
    server {
        listen       443 ssl;
        server_name  www.vip9999.top;
        
        ssl_certificate cert/214025315060640.pem;
        ssl_certificate_key cert/214025315060640.key;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
​
        #pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php$ {
            root           /usr/share/nginx/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
            }
        }
相关推荐
Lovyk15 分钟前
Linux 正则表达式
linux·运维
Fireworkitte1 小时前
Ubuntu、CentOS、AlmaLinux 9.5的 rc.local实现 开机启动
linux·ubuntu·centos
sword devil9002 小时前
ubuntu常见问题汇总
linux·ubuntu
ac.char2 小时前
在CentOS系统中查询已删除但仍占用磁盘空间的文件
linux·运维·centos
中科米堆3 小时前
中科米堆CASAIM自动化三维测量设备测量汽车壳体直径尺寸
运维·自动化·汽车·视觉检测
淮北也生橘123 小时前
Linux的ALSA音频框架学习笔记
linux·笔记·学习
缘华工业智维4 小时前
CNN 在故障诊断中的应用:原理、案例与优势
大数据·运维·cnn
开航母的李大5 小时前
软件系统运维常见问题
运维·服务器·系统架构·运维开发
华强笔记6 小时前
Linux内存管理系统性总结
linux·运维·网络
十五年专注C++开发7 小时前
CMake进阶: CMake Modules---简化CMake配置的利器
linux·c++·windows·cmake·自动化构建