先看问题
boss提了一个怪异的需求:每天上班时间8.30-18点可以访问某些url,其他时间段403。
如何解决
可以使用nginx的ngx_http_map_module模块结合ngx_http_access_module模块来实现
具体操作步骤如
1.在nginx中定义map,用来映射时间段,开关状态,url信息
#nginx $time_local 是一个nginx配置文件中的变量,它可以输出当前时间的本地时间戳,格式为:
#[dd/MM/yyyy:HH:mm:ss +0800],其中+0800表示当前时区为东八区
```
map $time_local $enable_feature {
default off;
"~^[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:0[8]:[3-5][0-9]:[0-5][0-9]" on;
"~^[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:0[9]:[0-5][0-9]:[0-5][0-9]" on;
"~^[0-9]{2}/[a-zA-Z]{3}/[0-9]{4}:1[0-7]:[0-5][0-9]:[0-5][0-9]" on;
}
map $request_uri $block {
default 0;
~/servicegateway/test1/web1 1;
~/servicegateway/test2/web2 1;
}
map $block$enable_feature $forbid {
default 0;
lon 1;
}
```
2.在需要开关的配置项中使用if语句判断开关状态
if ($forbid = 0){
return 403;
}
#注意:使用if语句和map模块可能会影响nginx性能,建议在高并发场景下使用其他方法实现
正则详解:
以下是匹配nginx日志中时间的正则表达式:
```
\d{1,2}/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}[+-]\d{4}
```
这个正则表达式可以匹配类似于以下格式的时间字符串:
```
01/Jan/2023:10:22:59 +0800
```
- `\d{2} | [0-9]{2}` 表示匹配两位数字
- `\w{3} | [a-zA-Z]{3}` 表示匹配三个字母
- `:` 和空格表示匹配一个冒号和空格
- `\s` 表示匹配一个空格
- `\+` 表示匹配一个加号
- `[+-]\d{4}` 表示匹配+或者-符号和四位数字
常用map定义
#根据访问的客户端访问不同的url
map $http_user_agent $mobile {
default 0;
~*mobile|nokia|iphone|ipad|android|samsung|htc|blackberry 1;
}
其他配置(可自行尝试):
map $time_local $enable_feature {
default 0;
~* "08:00-17:59" 1;
~* "00:00-07:59" 0;
}