Nginx配置文件location配置详解
location介绍
官方文档
location 指令是 nginx 中最关键的指令之一,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应,这其中较难理解的是多个 location 的匹配顺序,本文会作为重点来解释和说明。
开始之前先明确一些约定,我们输入的网址叫做请求 URI,nginx 用请求 URI 与 location 中配置的 URI 做匹配。
nginx文件结构
首先我们先简单了解 nginx 的文件结构,nginx 的 HTTP 配置,由ngx_http_core_module模块引入。nginx的HTTP配置主要包括四个区块,结构如下:
http {//协议级别
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
gzip on;
upstream {//负载均衡配置
...
}
server {//服务器级别,每个server类似于httpd中的一个<VirtualHost>
listen 80;
server_name localhost;
location / {//请求级别,类似于httpd中的<Location>,用于定义URL与本地文件系统的映射关系
root html;
index index.html index.htm;
}
}
}
http{}段配置指令:
server {}:定义一个虚拟主机,示例如下:
server {
listen 80;
server_name www.idfsoft.com;
root "/vhosts/web";
}
listen:指定监听的地址和端口
listen address[:port];
listen port;
server_name NAME […]; 后面可跟多个主机,名称可使用正则表达式或通配符
当有多个server时,匹配顺序如下:
- 先做精确匹配检查
- 左侧通配符匹配检查,如*.idfsoft.com
- 右侧通配符匹配检查,如mail.*
- 正则表达式匹配检查,如~ ^.*.idfsoft.com$
default_server
root path; 设置资源路径映射,用于指明请求的URL所对应的资源所在的文件系统上的起始路径
alias path; 用于location配置段,定义路径别名
index file; 默认主页面
index index.php index.html;
error_page code […] [=code] URI | @name 根据http响应状态码来指明特用的错误页面,例如 error_page 404 /404_customed.html
[=code]:以指定的响应码进行响应,而不是默认的原来的响应,默认表示以新资源的响应码为其响应码,例如 error_page 404 =200 /404_customed.html
log_format 定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
//注意:此处可用变量为nginx各模块内建变量
location区段,通过指定模式来与客户端请求的URI相匹配
//功能:允许根据用户请求的URI来匹配定义的各location,匹配到时,
//此请求将被相应的location配置块中的配置所处理,
//例如做访问控制等功能
//语法:location [ 修饰符 ] pattern {......}
常用修饰符说明:
修饰符 | 功能 |
---|---|
= | 精确匹配 |
~ | 正则表达式模式匹配,区分大小写 |
~* | 正则表达式模式匹配,不区分大小写 |
^~ | 前缀匹配,类似于无修饰符的行为,也是以指定模块开始,不同的是,如果模式匹配,那么就停止搜索其他模式了,不支持正则表达式 |
@ | 定义命名location区段,这些区段客户端不能访问,只可以由内部产生的请求来访问,如try_files或error_page等 |
没有修饰符表示必须以指定模式开始,如:
server {
server_name www.idfsoft.com;
location /abc {
......
}
}
那么如下内容就可正确匹配:
- http://www.idfsoft.com/abc
- http://www.idfsoft.com/abc?p1=11&p2=22
- http://www.idfsoft.com/abc/
=:表示必须与指定的模式精确匹配,如:
server {
server_name www.idfsoft.com;
location = /abc {
......
}
}
那么如下内容就可正确匹配:
- http://www.idfsoft.com/abc
- http://www.idfsoft.com/abc?p1=11&p2=22
如下内容则无法匹配:
- http://www.idfsoft.com/abc/
- http://www.idfsoft.com/abc/abcde
~:表示指定的正则表达式要区分大小写,如:
server {
server_name www.idfsoft.com;
location ~ ^/abc$ {
......
}
}
那么如下内容就可正确匹配:
- http://www.idfsoft.com/abc
- http://www.idfsoft.com/abc?p1=11&p2=22
如下内容则无法匹配:
- http://www.idfsoft.com/abc/
- http://www.idfsoft.com/ABC
- http://www.idfsoft.com/abcde
~*:表示指定的正则表达式不区分大小写,如:
server {
server_name www.idfsoft.com;
location ~* ^/abc$ {
......
}
}
那么如下内容就可正确匹配:
- http://www.idfsoft.com/abc
- http://www.idfsoft.com/abc?p1=11&p2=22
- http://www.idfsoft.com/ABC
如下内容则无法匹配:
- http://www.idfsoft.com/abc/
- http://www.idfsoft.com/abcde
~:类似于无修饰符的行为,也是以指定模式开始,不同的是,如果模式匹配,则停止搜索其他模式
查找顺序和优先级:由高到底依次为
1.先精准匹配 = ,精准匹配成功则会立即停止其他类型匹配;
2.没有精准匹配成功时,进行前缀匹配。先查找带有 ^~ 的前缀匹配,带有 ^~ 的前缀匹配成功则立即停止其他类型匹配,普通前缀匹配(不带参数 ^~ )成功则会暂存,继续查找正则匹配;
3.= 和 ^~ 均未匹配成功前提下,查找正则匹配 ~ 和 ~* 。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配;
4.所有正则匹配均未成功时,返回步骤 2 中暂存的普通前缀匹配(不带参数 ^~ )结果
以上规则简单总结就是优先级从高到低依次为(序号越小优先级越高)
1. location = # 精准匹配
2. location ^~ # 带参前缀匹配
3. location ~ # 正则匹配(区分大小写)
4. location ~* # 正则匹配(不区分大小写)
5. location /a # 普通前缀匹配,优先级低于带参数前缀匹配。
6. location / # 任何没有匹配成功的,都会匹配这里处
#案例分析
//修改配置文件
//删除原来location的内容添加新的内容
[root@Masters ~]# vim /usr/local/nginx/conf/nginx.conf
42
43 location = / {
45 echo "[ configuration A ]"; //绝对引用根访问时IP打印"[ configuration A ]"
46 }
47
48 location / {
49 echo "[ configuration B ]"; //在根下的文件打印"[ configuration B ]"
50 }
51
52 location /documents/ {
53 echo "[ configuration C ]"; //在根下的/documents/目录下文件及目录打印"[ configuration C ]"
54 }
55
56 location ^~ /images/ {
57 echo "[ configuration D ]"; //在根下的/images/目录下的文件及目录打印"[ configuration D ]"
58 }
59
60 location ~* \.(gif|jpg|jpeg)$ { //在根下的以.(gif|jpg|jpeg)结尾的文件打印"[ configuration E ]"
61 echo "[ configuration E ]";
62 }
[root@Masters ~]# nginx -s reload
[root@Masters ~]# systemctl restart nginx.service
[root@Masters ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
详细注解:
location = / {
# 只精准匹配 / 的查询.
[ configuration A ]
}
#匹配成功: /
location / {
# 匹配任何请求,因为所有请求都是以”/“开始
# 但是更长字符匹配或者正则表达式匹配会优先匹配
[ configuration B ]
}
#匹配成功:/index.html
location /documents {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索/
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条/
[ configuration C ]
}
#匹配成功:/documents/document.html
#匹配成功:/documents/abc
location ~ /documents/ABC {
# 区分大小写的正则匹配
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索/
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条/
[ configuration CC ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开头的地址,匹配符合以后,立即停止往下搜索正则,采用这一条。/
[ configuration D ]
}
#成功匹配:/images/a.gif
location ~* .(gif|jpg|jpeg)$ {
# 匹配所有以 .gif、.jpg 或 .jpeg 结尾的请求,不区分大小写
# 然而,所有请求 /images/ 下的图片会被 [ config D ] 处理,因为 ^~ 到达不了这一条正则/
[ configuration E ]
}
#成功匹配:/documents/a.jpg
location /images/ {
# 字符匹配到 /images/,继续往下,会发现 ^~ 存在/
[ configuration F ]
}
location /images/abc {
# 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在/
# F与G的放置顺序是没有关系的/
[ configuration G ]
}
location ~ /images/abc/ {
# 只有去掉 [ config D ] 才有效:先最长匹配 [ config G ] 开头的地址,继续往下搜索,匹配到这一条正则,采用/
[ configuration H ]
}
访问控制
用于location段
allow:设定允许哪台或哪些主机访问,多个参数间用空格隔开
deny:设定禁止哪台或哪些主机访问,多个参数间用空格隔开
示例:
allow 192.168.1.1/32 172.16.0.0/16;
deny all;
实践:
//拒接本机访问
location / {
echo "GUI";
deny 192.168.79.1;
}
//除本主机外拒接所有访问
注意!deny all要写在后面,因为是依次检查规则的,如果第一条直接写deny all,下面的就不会被匹配到了。
location / {
echo "GUI";
allow 192.168.79.1;
deny all;
}
基于用户认证
auth_basic “欢迎信息”;
auth_basic_user_file “/path/to/user_auth_file”
user_auth_file内容格式为:
username:password
这里的密码为加密后的密码串,建议用htpasswd来创建此文件:
htpasswd -c -m /path/to/.user_auth_file USERNAME
实践:
//下载httpd-tools
[root@Masters ~]# yum -y install httpd-tools
//修改配置文件
[root@Masters ~]# vim /usr/local/nginx/conf/nginx.conf
location = / {
root html;
auth_basic "Welcome home!"
auth_basic_user_file ".htpasswd"
echo "GHI";
}
//创建密码文件
[root@Masters ~]# cd /usr/local/nginx/conf/
[root@Masters conf]# htpasswd -c -m /usr/local/nginx/conf/.htpasswd GUI
New password:
Re-type new password:
Adding password for user GUI
[root@Masters conf]# cat .htpasswd
GUI:$apr1$DX3M6FYG$5U1/X02PWEaU.NGs2HjYA/
开启状态页面
官方文档
开启status:
location /status {
stub_status {on | off};
allow 172.16.0.0/16;
deny all;
}
访问状态页面的方式:http://server_ip/status
状态页面信息详解:
状态码 | 表示的意义 |
---|---|
Active connections 2 | 当前所有处于打开状态的连接数 |
accepts | 总共处理了多少个连接 |
handled | 成功创建多少握手 |
requests | 总共处理了多少个请求 |
Reading | nginx读取到客户端的Header信息数,表示正处于接收请求状态的连接数 |
Writing | nginx返回给客户端的Header信息数,表示请求已经接收完成,且正处于处理请求或发送响应的过程中的连接数 |
Waiting | 开启keep-alive的情况下,这个值等于active - (reading + writing),意思就是Nginx已处理完正在等候下一次请求指令的驻留连接 |
实践:
//开启状态页面
location = /status {
stub_status;
}
//开启状态页面基于用户认证
location = /status {
stub_status;
auth_basic "GHI";
auth_basic_user_file ".htpasswd";
}
https配置
生成私钥,生成证书签署请求并获得证书,然后在nginx.conf中配置如下内容:
server {
listen 443 ssl;
server_name www.idfsoft.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
实践使用OpenSSL实现:
//创建存放位置
[root@Masters ~]# cd /etc/Gin/KI/
[root@Masters KI]# mkdir private
//生成密钥
[root@Masters KI]# umask 077;openssl genrsa -out private/cakey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................................+++++
.........................................................................................+++++
e is 65537 (0x010001)
//提取公钥
[root@Masters KI]# openssl rsa -in private/cakey.pem -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrcm52Nt2eLvdNOnbGMy
yigtRYK+w9ZXanb/8dVvLrAtU3LQb3fBNUU8z3EBegNp+b8SXHbGIx5/3cYuv9tH
duhY7YjccVY+ldyj9zheodXsXctX251hZ6oUPONFM/QnRzBooH2TQTXhnyq6D/zx
71mAHVAf5DlZ8DoJlmxnx50rtPOlc/7LRVQs4edUQiUaHSS93+CmSer1ICS5WKfo
Psg2peL6GrHTsUyqY8Cf210qq62fL8BOpvHXzUIJiIZjxV8/cho4BxccnstvDMrt
RmWWVKvGTFlDoyJQvBFWmLYXFqAmAdOFMAe8KHnY9iVZLryRI/P0z00Ouk3JG2od
RQIDAQAB
-----END PUBLIC KEY-----
//生成自签发证书
[root@Masters KI]# openssl rsa -in private/cakey.pem -pubout
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyrcm52Nt2eLvdNOnbGMy
yigtRYK+w9ZXanb/8dVvLrAtU3LQb3fBNUU8z3EBegNp+b8SXHbGIx5/3cYuv9tH
duhY7YjccVY+ldyj9zheodXsXctX251hZ6oUPONFM/QnRzBooH2TQTXhnyq6D/zx
71mAHVAf5DlZ8DoJlmxnx50rtPOlc/7LRVQs4edUQiUaHSS93+CmSer1ICS5WKfo
Psg2peL6GrHTsUyqY8Cf210qq62fL8BOpvHXzUIJiIZjxV8/cho4BxccnstvDMrt
RmWWVKvGTFlDoyJQvBFWmLYXFqAmAdOFMAe8KHnY9iVZLryRI/P0z00Ouk3JG2od
RQIDAQAB
-----END PUBLIC KEY-----
[root@Masters KI]# openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:www.Gin.com
Organizational Unit Name (eg, section) []:www.Gin.com
Common Name (eg, your name or your server's hostname) []:www.Gin.com
Email Address []:123@5.com
[root@Masters KI]# ls
cacert.pem private
[root@Masters KI]# mkdir certs newcerts crl
[root@Masters KI]# touch index.txt && echo 01 > serial
[root@Masters KI]# ls
cacert.pem certs crl index.txt newcerts private serial
[root@Masters KI]# cd /usr/local/nginx/conf/
[root@Masters conf]# mkdir ssl
[root@Masters conf]# cd ssl/
//客户端证书
[root@Masters ssl]# umask 077;openssl genrsa -out nginx.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...........................+++++
.............................................+++++
e is 65537 (0x010001)
[root@Masters ssl]# openssl req -new -key nginx.key -days 365 -out nginx.csr
Ignoring -days; not generating a certificate
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:^C
[root@Masters ssl]# openssl req -new -key nginx.key -days 365 -out nginx.csr
Ignoring -days; not generating a certificate
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:HB
Locality Name (eg, city) [Default City]:WH
Organization Name (eg, company) [Default Company Ltd]:www.Gin.com
Organizational Unit Name (eg, section) []:www.Gin.com
Common Name (eg, your name or your server's hostname) []:www.Gin.com
Email Address []:123@5.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123
string is too short, it needs to be at least 4 bytes long
A challenge password []:
An optional company name []:
[root@Masters ssl]# ls
nginx.csr nginx.key
//部署
[root@Masters ssl]# openssl ca -in nginx.csr -out nginx.crt -days 365
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Oct 13 20:35:41 2022 GMT
Not After : Oct 13 20:35:41 2023 GMT
Subject:
countryName = CN
stateOrProvinceName = HB
organizationName = www.Gin.com
organizationalUnitName = www.Gin.com
commonName = www.Gin.com
emailAddress = 123@5.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
04:7E:A7:7C:55:34:E8:B8:52:D0:C5:CE:FA:C4:14:E2:A5:96:08:A2
X509v3 Authority Key Identifier:
keyid:76:81:2D:69:5B:17:F6:52:4C:C4:91:7C:BC:FD:90:21:01:C0:49:F7
Certificate is to be certified until Oct 13 12:38:41 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
[root@Masters ssl]# ls
nginx.crt nginx.csr nginx.key
[root@Masters ssl]# rm -f nginx.csr
[root@localhost ssl]# ls
nginx.crt nginx.key
rewrite
语法:rewrite regex replacement flag;,如:
rewrite ^/images/(.*.jpg)$ /imgs/$1 break;
此处的$1用于引用(.*.jpg)匹配到的内容,又如:
rewrite ^/bbs/(.*)$ http://www.idfsoft.com/index.html redirect;
如上例所示,replacement可以是某个路径,也可以是某个URL
常见的flag
|flag |作用|
|–|–|–|
|last |基本上都用这个flag,表示当前的匹配结束,继续下一个匹配,最多匹配10个到20个 一旦此rewrite规则重写完成后,就不再被后面其它的rewrite规则进行处理 而是由UserAgent重新对重写后的URL再一次发起请求,并从头开始执行类似的过程|
|break |中止Rewrite,不再继续匹配 一旦此rewrite规则重写完成后,由UserAgent对新的URL重新发起请求, 且不再会被当前location内的任何rewrite规则所检查|
|redirect |以临时重定向的HTTP状态302返回新的URL|
|permanent |以永久重定向的HTTP状态301返回新的URL|
rewrite模块的作用是用来执行URL重定向。这个机制有利于去掉恶意访问的url,也有利于搜索引擎优化(SEO)
nginx使用的语法源于Perl兼容正则表达式(PCRE)库,基本语法如下:
标识符 | 意义 |
---|---|
^ | 必须以^后的实体开头 |
$ | 必须以$前的实体结尾 |
. | 匹配任意字符 |
[] | 匹配指定字符集内的任意字符 |
[^] | 匹配任何不包括在指定字符集内的任意字符串 |
() | 分组,组成一组用于匹配的实体,通常会有 |
捕获子表达式,可以捕获放在()之间的任何文本,比如:
^(hello|sir)$ //字符串为“hi sir”捕获的结果:$1=hi$2=sir
//这些被捕获的数据,在后面就可以当变量一样使用了
示例:
案例1:将匹配到的URI重写至其它本机下的其它资源位置
#匹配到以images开头,以.jpg结尾的URI,重定向到imgs目录下的以.jpg结尾的文件
#$1是引用都第一个挂号内匹配到的内容
[root@nginx conf]# vim nginx.conf
..............
location /images {
rewrite ^/images/(.*\.jpg)$ /images/$1 break;
}
...............
[root@Masters ~]# cd /usr/local/nginx/html/
[root@Masters html]# mkdir images
[root@Masters html]# cd images/
[root@Masters images]# ls
test.jpg
[root@Masters ~]# systemctl reload nginx.service
案例2:将匹配到的URI重写至其它网页
#匹配到以ll开头的,/后面是任意内容的URI时,将重定向至www.zealf.red
[root@nginx conf]# vim nginx.conf
.............
location /ll {
rewrite ^/ll/.*$ https://www.zealf.red;
}
.............
[root@Masters ~]# cd /usr/local/nginx/html/
[root@Masters html]# mkdir ll
[root@Masters html]# systemctl reload nginx.service
if
语法:if (condition) {…}
应用场景:文章来源:https://www.toymoban.com/news/detail-448438.html
- server段
- location段
常见的condition文章来源地址https://www.toymoban.com/news/detail-448438.html
- 变量名(变量值为空串,或者以“0”开始,则为false,其它的均为true)
- 以变量为操作数构成的比较表达式(可使用=,!=类似的比较操作符进行测试)
- 正则表达式的模式匹配操作
- ~:区分大小写的模式匹配检查
- ~*:不区分大小写的模式匹配检查
- !和!*:对上面两种测试取反
- 测试指定路径为文件的可能性(-f,!-f)
- 测试指定路径为目录的可能性(-d,!-d)
- 测试文件的存在性(-e,!-e)
- 检查文件是否有执行权限(-x,!-x)
基于浏览器实现分离案例
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
防盗链案例
location ~* \.(jpg|gif|jpeg|png)$ {
valid_referers none blocked www.idfsoft.com;
if ($invalid_referer) {
rewrite ^/ http://www.idfsoft.com/403.html;
}
}
到了这里,关于Nginx配置文件配置详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!