2025年6月8日 星期日 乙巳(蛇)年 三月十二 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 服务器 > Nginx

nginx的rewrite重写及防盗链

时间:11-20来源:作者:点击数:23
城东书院 www.cdsy.xyz

rewrite相关:

利用ngx_http_rewrite_module模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression)

因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能

比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问,另外还可以在一定程度上提高网站的安全性(防盗链)

官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html

模块的指令:

if指令:

官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if

不支持if else、if elif等多重判断,一个if一次性,false不继续,true继续

  • if (条件匹配) {
  • 操作
  • }

匹配条件的符号:

支持正则表达式,匹配成功为true

与shell的很相似

   
= 字符串的等于
~ 开启正则表达式,区分大小写
~* 开启正则表达式,不区分大小写
-f 文件是否存在
-d 目录是否存在
-x 文件是否有执行权限
-e 文件、目录、软链接是否存在

注意:

  • $变量的值为空、为0时,if判断为false
  • nginx 1.0.1之前$变量的值如果以0开头的任意字符串会返回false
例:

结合前一篇的文章中的第三方模块:echo模块测试

  • location /x {
  • if ($scheme = http) {
  • echo '$scheme is http';
  • }
  • if ($scheme = https) {
  • echo '$scheme is https';
  • }
  • if (!-e $request_filename) {
  • echo '$request_filename is not exist';
  • }
  • }

set指令:

普通的变量赋值

break指令:

与其他编程语言一样,break用于打断本次

用于server、location、if段,if和location中会跳出本次

例:
  • location /x {
  • echo 'one';
  • if ($scheme ~* http) {
  • echo '123';
  • break;
  • }
  • echo 'two';
  • break;
  • echo 'three';
  • }

return指令:

用于server、if、location中

return用于完成对请求的处理,并直接向客户端返回响应状态码,比如:可以指定重定向URL(对于特殊重定向状态码,301/302等)或者是指定提示文本内容(对于特殊状态码403/500等),处于此指令后的所有配置都将不被执行

  • return [状态码/状态码] 字符或变量或url;
例:
  • location /t {
  • root /opt/web;
  • if ($scheme ~* http) {
  • echo 'is http';
  • return 666 "not allow http";
  • }
  • if ($host ~* www.hj.com) {
  • return www.baidu.com; #访问www.hj.com直接跳转到百度
  • }
  • }

rewrite_log指令:

ngx_http_rewrite_module模块日志记录到error_log日志文件当中

配置在http、server、location 或 if 中

一般不建议开启,增加了cpu和磁盘消耗

注意:需要错误日志级别为notice

例:
  • server {
  • error_log /opt/nginx/logs/err.log notice;
  • location /t {
  • rewrite_log on;
  • }
  • }

rewrite指令:

用于server、location、if

通过正则表达式的匹配来改变URI,可以同时存在一个或多个指令,按照顺序依次对URI进行匹配,rewrite主要是针对用户请求的URL或者是URI做具体处理

正则表达式与shell的类似

官方文档:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite

注意:

  • 如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;
  • 被某条件规则替换完成后,会重新一轮的替换检查,隐含有循环机制,但不超过10次
  • 如果超过10次,提示500响应码,[flag]所表示的标志位用于控制此循环机制,如果替换后的URL是以http://或https://开头,则替换结果会直接以重定向返回给客户端, 即永久重定向 301
格式:
  • rewrite 正则表达式 替换后的内容 [标志位];

正则表达式格式:

   
. 除换行符以外的任意字符
\w 字母、数字、下划线、汉字
\s 任意空白符
\d 数字
\b 单词的开始或结束
^ 以什么开始
$ 以什么结束
* 重复0次或多次
+ 重复1次或多次
? 匹配0次或1次
(n) 重复n次
  重复n次或多次
  重复n到m次
*? 任意次,但尽可能少重复
+? 1次或多次,但尽可能少重复
?? 0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
\W 除字母、数字、下划线、汉字以外的字符
\S 除空白符以外
\D 除数字以外
\B 除单词开头或结束的位置
[^abc] 除abc以外的字符

标志位:

前两种是跳转型的flag,后两种是代理型:

  • 跳转型指由客户端浏览器重新对新地址进行请求
  • 代理型指是在WEB服务器内部实现跳转

一般做域名重写使用跳转型,做location重写做代理型

  • redirect
  • 状态码:302,域名的临时调整,之前的域名和url可能还会用,或者新跳转的目标域名和url还会跳转,这种状态码浏览器不会缓存到本地
  • 临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求
  • 用相对路径,或者http://或https://开头
  • permanent
  • 状态码:301,域名永久调整,旧域名不可用,访问时永久跳转到新域名和url,这种状态码浏览器会缓存到本地磁盘
  • 重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求
  • break
  • 重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
  • 适用于一个URL一次重写
  • last
  • 重写完成后,停止对当前URI所在的location中后续的其它重写操作,而后对新的location的URL启动新一轮重写检查,不建议在location中使用
  • 适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回500错误的给用户
例1: 域名永久和临时重定向
  • location / {
  • rewrite /a http://www.qq.com redirect;
  • rewrite /b http://www.baidu.com permanent;
  • }
image

例2:break场景:有V1/V2两个版本的网站前端页面并存,旧版本的网站数据在statics,还不能丢失,但是要将访问新版本的请求重写到新的静态资源路径static

  • mkdir /opt/web/{static,statics}
  • echo old > /opt/web/static/index.html
  • echo new > /opt/web/statics/index.html
  • vim nginx.conf
  • server {
  • location /statics {
  • root /opt/web;
  • rewrite ^/statics/(.*) /static/$1 break;
  • location /static {
  • root /opt/web;
  • }
  • }
  • nginx -s reload
  • #测试访问,返回的资源来自于: /opt/web/static/资源
  • curl -L 127.0.0.1/break

例3:不改变客户端访问方式但是需做多次目的URL重写的场景,使用场景不是很多

  • server {
  • location /last {
  • rewrite ^/last/(.*) /ts1/$1 last; #访问/last跳转访问/ts1
  • rewrite ^/ts1/(.*) /ts2/$1 last; #访问/ts1跳转访问/ts2
  • }
  • location /ts1 {
  • echo $uri;
  • }
  • location /ts2 {
  • echo $uri;
  • }
  • }
例4: 自动跳转https

目前主流网站的实现方式都是此,比如访问:http://www.baidu.com ,会自动跳转到:https://www.baidu.com

注意:做全站https时,不用写其他二级目录location,有其他需要时写在/的location就行,否则每个二级目录location都要写rewrite

  • server {
  • location / { #全站https
  • if ($scheme = http) {
  • rewrite / https://$host permanent;
  • }
  • }
  • location /login { #单url做https
  • if ($scheme = http) { #必须配合if,否则变成死循环
  • rewrite ^/(login)$ https://$host/$1 permanent;
  • }
  • }
  • }
例5:当用户访问到公司网站的时输入了一个错误的URL,可以将用户重定向至官网首页

京东商城的错误页跳转就是此实现的,在京东输入错误的页面,总是能跳转到首页

image
  • server {
  • location / {
  • if (!-e $request_filename){
  • rewrite (.*) http://$host/index.html;
  • }
  • }
  • }
例6: 根据不同的客户端浏览器重定向
  • server {
  • location / {
  • if ( $http_user_agent ~* MSIE ){ #ie浏览器使用此url资源
  • rewrite ^(.*)$ /msie/$1 break;
  • }
  • if ( $http_user_agent ~* chrome ){ #谷歌浏览器使用此url资源
  • rewrite ^(.*)$ /chrome/$1 break;
  • }
  • }
  • }
例7: 生产场景更换目录访问方式

要求:/20201002/static --> /static?id=20201002

  • location / {
  • rewrite ^/(\d+)/(\.+)/ /$2?id=$1 last;
  • #或者
  • rewrite ^/(\d+)/(.*)/ /$2?id=$1 last;
  • }
例8: 多级目录访问方式转换

要求:www.hj.com/images/20200106/1.jpg --> www.hj.com/index.do?name=images&dir=20200106=&file=1.jpg

  • location / {
  • if ($host ~* .*\.hj.com\.com) {
  • rewrite ^/(.*)/(\d+)/(.*)$ /index.do?name=$1&dir=$2$file=$3 last;
  • }
  • }

防盗链技术:

官方文档:https://nginx.org/en/docs/http/ngx_http_referer_module.html

由ngx_http_referer_module模块提供,用于server、location

防盗链基于客户端携带的referer实现,referer是记录上一个网站是谁,相当于记录网页跳转上下文。一般统计此记录进行分析、日志记录、缓存优化

如:www.baidu.com-->www.qq.com时,在www.qq.com查看referer,记录的就是www.baidu.com

image

如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,如频繁访问图片、视频等,这就是盗链

  • vaild_referers 参数1 参数2 ...; 指定合法的referers
  • 参数:
  • none 请求报文没有referer首部,用户访问时没有使用搜索引擎,直接输入域名时,没有referer信息。意思是直接引用的链接。合法引用
  • blocked 请求报文的referer为空时,合法引用
  • server_names referer首部包含本机nginx监听的server_name和公司内其他主机名
  • string 自定义指定字符串,可使用通配符“*”,如*.hj.com
  • 正则表达式 使用正则表达式匹配字符串,必须以“~”开始,如:~.*\.hj\.com
例: 实现防盗链

实际上就是允许哪些跳转路径为合法,为匹配的referer都拒绝

建议把访问日志格式改为json格式的,方便后期做日志分析

  • server {
  • location ~* \.(jpg|png|jpeg|gif)$ {
  • #允许本域名和相关搜索引擎为合法
  • valid_referers none blocked server_names
  • www.hj.*/img/ ~\.baidu\. ~\.google\.
  • ~\.baidu\. ~\.bing\. ~\.so\. ~\.dogedoge\.;
  • if ($invalid_referer) {
  • return 403 "Forbidden Access"; #不合法的referer都返回403
  • }
  • }
  • }
城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐