Nginx URL重写模块 ngx_http_rewrite_module

欢迎大家关注本博,同时欢迎大家评论交流,可以给个赞哦!!!

  ngx_http_rewrite_module模块用于使用PCRE正则表达式更改请求URI,返回重定向并有条件的配置。

  URL 重写

  首先,需要了解什么是URL重写?

  URL重写即是将接收的一个URL请求重写成网站可处理的另一个URL的过程。例如:浏览器请求的URL是“/securitit.html?sex=man”,那么经过重写可以变为“/secutitit.html”,当然可以变成任意格式,具体格式都是根据业务需要的应用场景决定的。

  其次,为什么需要使用URL重写?

  URL重写在很多业务场景中都有应用,在某些特定领域和业务场景下,解决特定问题。

  · URL重写支持会话

  浏览器禁用Cookie时,可以把会话ID附加在URL后面响应给浏览器,形如“/secutitit.html?sessionId=xxxxxxxx”,这样在浏览器发送请求时,会话ID会自动发送给服务器。

  一般来说,URL重写支持会话是非常健壮的方式,因其可以避免浏览器不支持Cookie的情况,但URL重写支持会话同样存在很多问题:

  1.安全性问题,会话ID附加在URL之后,很大程度上,将服务器分配给浏览器的认证信息暴露在外,对于服务安全来说,有弊无利。

  2.URL重写支持会话,要求应用中所有的页面都是动态的,因为不同的浏览器客户端需要不同的会话ID。

  3.URL重写支持会话,要求所有静态页面必须经过统一Servlet处理器,在响应之前进行URL重写。

  · SEO 搜索优化

  搜索引擎喜欢静态页面,因此,若希望网站得到更高的收录率,则需对网站动态URL进行静态化处理,实现的方式也就是URL重写。

  · URL 安全性

  可以针对异常的URL,包括用户输入错误的URL、不存在的URL重定向到404页面或其他描述页面,可以避免服务器返回详细的描述,暴露服务器信息。

  · 易于用户记忆

  URL 重写模块 配置安装

  在初始配置时,能会出现如下的错误,这是由于系统缺少PCRE库,使用yum -y install pcre安装即可。
在这里插入图片描述
  URL 重写模块 语法及语义

  ngx_http_rewrite_module提供了break、if、return、rewrite、set指令,用来完成URL重写,接下来一一分析其语法使用。

  break

   语法:break;

   语义:立即停止rewrite检测。

  if

   语法:if(condition) { … }

   语义:

   若condition为true,则执行括号内指定的此模块指令,并在指令内为请求分配配置if。if指令中的配置是从先前的配置级别继承的。

   条件可以是以下任一种:

   · 变量名:如果变量的值为空字符串或"0",则为false,否则为false。在1.0.1版之前,任何以"0"开头的字符串都被视为false。

   · 使用"=“和”!="运算符将变量与字符串进行比较。

   · 使用""(区分大小写的匹配)和" *"(不区分大小写的匹配)运算符将变量与正则表达式进行匹配。正则表达式可以包含捕获,这些捕获可用于以后在$1…$9变量中重用。负运算符"!“和”! *“也可用。如果正则表达式包含”}“或”;"字符,则整个表达式应用单引号或双引号引起来。

   · 使用"-f"和"!-f"运算符检查文件是否存在。

   · 使用"-d"和"!-d"运算符检查目录是否存在。

   · 使用"-e"和"!-e"运算符检查文件,目录或符号链接是否存在;

   · 使用"-x"和"!-x"运算符检查可执行文件。

   示例:

   这是取自官网的示例,下面对这几个例子进行解析:

# 匹配user_agent头为MSIE时(即IE浏览器),进行URL重写.
if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}
# 匹配cookie,如果cookie匹配正则,设置变量$id等于正则引用部分.
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}
# 请求是否是POST.
if ($request_method = POST) {
    return 405;
}
# 限速,$slow可以通过set指令设置.
if ($slow) {
    limit_rate 10k;
}
# // 通过referer实现防盗链.
if ($invalid_referer) {
    return 403;
}

  return

   语法:return code [text];

      return code URL;

      return URL;

   语义:

​   停止处理并将指定的返回code给客户端。非标准代码444关闭连接而不发送响应头。

   从版本0.8.42开始,可以指定重定向URL(对于代码301、302、303、307和308)或响应正文text(对于其他代码)。响应正文和重定向URL可以包含变量。在特殊情况下,可以将重定向URL指定为该服务器本地的URI,在这种情况下,完整的重定向URL会根据请求方案($scheme)以及server_name_in_redirect和 port_in_redirect指令形成。

  rewrite

   语法:rewrite regex replacement [flag];

   语义:

   使用regex正则表达式与请求URI进行匹配,若可以匹配,则按照replacement指定的方式进行更改。rewrite指令在配置文件中按照出现的顺序执行。

   flag为可选参数,其值可为下列中任一值:

   last

    停止rewrite检测, 并开始搜索与更改后的URI相匹配的新位置。

   break

    与break指令一样,立即停止rewriet检测。

   redirect

    返回带有302代码的临时重定向。

   permanent

    返回带有301代码的永久重定向。

   完整的重定向URL是根据请求方案($scheme)以及server_name_in_redirect和port_in_redirect指令形成的。

  rewrite_log

   语法:rewrite_log on | off;

   语义:

    开启或禁用日志记录,日志记录会将notice级别日志记录到error_log中。

  set

   语法:set $variable value;

   语义:

   为变量variable赋值value,value可以包括文本、变量或它们的组合。

  URL 重写模块 示例

  为演示效果,在/usr/local/nginx/html/目录下新建first和second两个目录,目录中各自新建test.html,详情如下:
在这里插入图片描述
  test.html内容很简单,只有一段文本,为做区分,first和second目录下的test.html内容稍有差异:
在这里插入图片描述
  修改nginx.conf,配置文件中涉及break、if、return、rewrite指令:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
     	}

        location /withbreak {
            rewrite ^/withbreak/(.*) /first/$1;
            break;
        }

        location /withoutbreak {
            rewrite ^/withoutbreak/(.*) /first/$1;
        }

        location /withlast {
            rewrite ^/withlast/(.*) /first/$1 last;
        }

        location /withoutlast {
            rewrite ^/withoutlast/(.*) /first/$1;
        }

        location ~ ^/regexStartl {
            rewrite ^/regexStartl.*/(.*) /first/$1;
        }

        location ~* ^/regexStartlu {
            rewrite ^/(?i)regexStartlu.*/(.*) /first/$1;
        }

        location ~* .*[&]+.* {
            return 905;
        }

        location /first {
            rewrite ^/first/(.*) /second/$1;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

  安装上面的配置,会出现以下几种情形:

  · 当访问http://192.168.20.9/withbreak/test.html时,经过重写后会访问http://192.168.20.9/first/test.html,由于配置了/first的过滤,http://192.168.20.9/first/test.html经过重写后会访问http://192.168.20.9/second/test.html。这样会经过两次重写,最终显示结果如下:
在这里插入图片描述
  · 当访问http://192.168.20.9/withoutbreak/test.html时,经过重写后会访问http://192.168.20.9/first/test.html,由于配置了break,会停止rewrite检测,会显示如下:
在这里插入图片描述
  · 当访问http://192.168.20.9/withlast/test.html时,经过重写后会访问http://192.168.20.9/first/test.html,由于配置了/first的过滤,http://192.168.20.9/first/test.html经过重写后会访问http://192.168.20.9/second/test.html。这样会经过两次重写,最终显示结果如下:
在这里插入图片描述
  · 当访问http://192.168.20.9/withoutlast/test.html时,经过重写后会访问http://192.168.20.9/first/test.html,由于配置了break,会停止rewrite检测,会显示如下:
在这里插入图片描述
  · 注意:

  使用break指令,如果匹配内容存在的话,可以直接请求成功,返回200。如果请求内容不存在,则返回404。

  使用rewrite regex replacement last时,如果匹配内容存在的话,可以直接请求成功,返回200。如果请求内容不存在,则会以当前URL再次发起重写匹配。

  break指令与rewrite regex replacement break指令效果一样。

  · 当访问http://192.168.20.9/regexStartl/test.html时,由于其condition包含~,区分大小写匹配:
在这里插入图片描述
  当将其路径大小写变化时,如http://192.168.20.9/RegexStartl/test.html,则匹配不成功,返回404:
在这里插入图片描述
  · 当访问http://192.168.20.9/regexstartlu/test.html时,由于其condition包含~*,不区分大小写匹配,可以任意变换路径的大小写格式:
在这里插入图片描述
在这里插入图片描述
  · 当访问http://192.168.20.9/ab&cd/test.html时,由于nginx.conf中的配置:

location ~* .*[&]+.* {
	return 905;
}

  正则表达式与URI匹配成功,则会返回对应的状态码,如下所示:
在这里插入图片描述
  总结

  URL重写在实际应用中还是比较频繁的,尤其是if (condition) { … },关于condition的执行顺序,需要说明一下:(location = ) > (location 完整路径) > (location ^~ 路径) > (location ~ |~* 正则顺序) > (location 部分起始路径) > (/),这在实际应用还是比较重要的。

  若文中存在错误和不足,欢迎指正!

本博微信公众号“超哥说码”,欢迎大家订阅,公众号正在完善中,会及时将更优质的博文推送于您!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/securitit/article/details/109090639