阅读量:3
Nginx自定义模块是Nginx得一种扩展功能,这里拿权限控制模块,我们通过编写模块来精确控制用户访问特定资源的权限,实现基于用户角色、IP地址、时间等多种策略的细粒度访问控制,从而增强网站安全性,这里得实例只校验基本token权限。
1. 功能概述
本模块用于对所有 HTTP 请求进行权限控制,通过 Redis 校验权限信息(Token)。如果 Token 验证失败,则返回 403 Forbidden 状态码。
2. 环境准备
确保你已经安装了 Redis,并且在 Nginx 开发环境中包含了 Redis 客户端库。
2.1 安装 Redis
sudo apt-get install redis-server
2.2 安装 Nginx 开发环境
sudo apt-get update sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev
2.3 下载 Nginx 源码
wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0
3. 创建自定义模块
3.1 创建模块目录和文件
在 Nginx 源码目录下创建一个新的目录用于存放模块:
mkdir -p ./src/http/modules/auth_module
3.2 编写模块代码
创建 auth_module.c
文件,代码如下:
// src/http/modules/auth_module/auth_module.c #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> #include <hiredis/hiredis.h> // Redis 客户端库 static redisContext *redis_conn; // Redis 连接初始化 static void init_redis() { redis_conn = redisConnect("127.0.0.1", 6379); if (redis_conn == NULL || redis_conn->err) { if (redis_conn) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "Redis connection error: %s", redis_conn->errstr); redisFree(redis_conn); } else { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "Can't allocate redis context"); } } } // 权限验证函数 static ngx_int_t auth_module_handler(ngx_http_request_t *r) { // 获取请求头中的 Token ngx_table_elt_t *auth_header = r->headers_in.authorization; if (auth_header == NULL) { return NGX_HTTP_FORBIDDEN; // 未提供 Token,返回 403 } // 查询 Redis 校验 Token redisReply *reply = redisCommand(redis_conn, "GET %s", auth_header->value.data); if (reply == NULL || reply->type == REDIS_REPLY_NIL) { return NGX_HTTP_FORBIDDEN; // Token 校验失败,返回 403 } freeReplyObject(reply); // 释放 Redis 回复对象 return NGX_OK; // 验证成功,继续处理请求 } // 创建模块的配置 static ngx_http_core_loc_conf_t *auth_module_create_conf(ngx_conf_t *cf) { return NULL; // 此模块不需要配置 } // 初始化模块 static ngx_http_core_main_conf_t *auth_module_init(ngx_conf_t *cf) { init_redis(); // 初始化 Redis 连接 return NULL; } // 模块命令定义 static ngx_command_t auth_module_commands[] = { { ngx_string("auth_module"), // 指令名称 NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS, // 配置类型 NULL, // 无配置处理函数 NGX_HTTP_LOC_CONF_OFFSET, // 偏移量 0, // 无额外参数 NULL }, ngx_null_command // 结束命令 }; // 模块上下文 static ngx_http_module_t auth_module_ctx = { NULL, // 预配置函数 NULL, // 后配置函数 NULL, // 创建主配置 NULL, // 初始化主配置 NULL, // 创建服务器配置 NULL, // 合并服务器配置 auth_module_create_conf, // 创建位置配置 NULL // 合并位置配置 }; // 模块定义 static ngx_module_t auth_module = { NGX_MODULE_V1, &auth_module_ctx, // 模块上下文 auth_module_commands, // 模块指令 NGX_HTTP_MODULE, // 模块类型 NULL, // 初始化主进程 NULL, // 初始化模块 NULL, // 初始化进程 NULL, // 初始化线程 NULL, // 退出线程 NULL, // 退出进程 NULL, // 退出主进程 NGX_MODULE_V1_PADDING // 填充 }; ngx_module_t *ngx_module = &auth_module; // 导出模块
4. 编译 Nginx 并加载模块
4.1 配置 Nginx
在 Nginx 源码目录中配置编译选项,并指定自定义模块:
./configure --add-module=src/http/modules/auth_module --with-http_ssl_module
4.2 编译和安装
make sudo make install
5. 配置 Nginx 使用模块
5.1 编辑 Nginx 配置文件
在 Nginx 配置文件(通常在 /etc/nginx/nginx.conf
)中添加自定义模块的配置:
http { ... server { listen 80; server_name localhost; location / { auth_module; # 使用自定义权限控制模块 } } }
5.2 启动 Nginx
启动或重启 Nginx 以应用配置:
sudo systemctl restart nginx
6. 测试模块
使用 curl 测试自定义模块的权限控制:
curl -H "Authorization: your_token" http://localhost/
如果 Token 验证成功,将返回相应的内容;如果失败,将返回 403 Forbidden 状态。
7. 相关 API 介绍
7.1 Nginx API 概述
Nginx 提供了一套丰富的 API,用于处理请求、管理连接、配置模块等。
7.1.1 请求处理 API
ngx_http_request_t
- 代表一个 HTTP 请求的上下文,包含与请求相关的数据。
ngx_http_send_header()
- 用于发送响应头。
- 参数:
ngx_http_request_t *r
- 请求上下文。 - 返回:
ngx_int_t
- 返回NGX_OK
表示成功。
ngx_http_finalize_request()
- 用于终止请求的处理并发送响应。
7.1.2 响应处理 API
ngx_buf_t
- 表示一个缓冲区,用于存储响应体。
ngx_http_headers_out_t
- 包含所有的响应头信息。
7.1.3 配置处理 API
ngx_command_t
- 定义模块的指令。
ngx_http_core_loc_conf_t
- 用于存储特定位置的配置。
ngx_conf_t
- 模块配置上下文。
7.2 Redis API
- hiredis
- C 语言的 Redis 客户端库。
- 常用函数包括
redisConnect()
,redisCommand()
,freeReplyObject()
等。
通过以上操作,我们成功创建并配置了一个 Nginx 自定义模块,利用 Redis 校验请求的权限信息。