版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/RoyalApex/article/details/26404379

1 需求

    要求在浏览器地址栏中输入"localhost/login?user=qifeng&passwd=123456",并在浏览器上显示验证结果(成功 或 失败)。下面是在NGINX中增加一个LOGIN模块的整个处理过程。

2 改动配置

  依据需求改动配置文件nginx.conf,在http{...}的server{...}中增加location配置信息:

图1 改动配置

(注意:将passwd的值"abcd"改为“123456”)

3 编写代码

3.1 创建源代码文件夹

    在NGINX源代码文件夹src下新建ext文件夹,src/ext用于存放全部扩展模块代码,src/ext/login则用于存放LOGIN模块的代码.

    #mkdir -p src/ext/login

    #cd src/ext/login

    #vim ngx_http_login_module.c

3.2 定义配置结构

  LOGIN模块主要实现的是对用户(user)和密码(password)的验证,因此,配置信息结构中须要包括user字段和password字段。故其结构定义例如以下:(命名规则:ngx_http_模块名_(main|srv|loc)conf_t)

/* 配置项结构体:用于存放配置项和相应值 */
typedef struct
{
ngx_str_t user;
ngx_str_t passwd;
}ngx_http_login_loc_conf_t;
代码1 定义配置结构

3.3 设置解析数组

  从图1中可知:配置项有user、passwd和check.解析这些配置项的配置项的解析是通过配置ngx_command_t数组,配置项解析数组例如以下:(命名规则:ngx_http_模块名_commands)

/* 配置项解析数组:配置指令是通过此数组依次解析的. */
static ngx_command_t ngx_http_login_commands[] =
{
{
ngx_string("user"), /* 配置项名 */
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1, /* 所属模块和配置值个数 */
ngx_conf_set_str_slot, /* 解析该配置项的回调 */
NGX_HTTP_LOC_CONF_OFFSET, /* 配置存储位置 */
offsetof(ngx_http_login_loc_conf_t, name), /* 配置值赋给的变量 */
NULL
},
{
ngx_string("passwd"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_login_loc_conf_t, passwd),
NULL
},
{
ngx_string("check"),
NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
ngx_http_login_check,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};

代码2 配置项解析数组

3.4 设置配置回调

    定义模块配置解析过程中各阶段的处理回调:(命名规则:ngx_http_模块名_module_ctx)

static ngx_http_module_t ngx_http_login_module_ctx =
{
NULL, /* 读入配置前的回调 */
NULL, /* 读入配置后的回调 */
NULL, /* 创建main配置时的回调 */
NULL, /* 初始化main配置时的回调 */
NULL, /* 创建srv配置时的回调 */
NULL, /* 合并srv配置时的回调 */
ngx_http_login_create_loc_conf, /* 创建loc配置时的回调 - LOGIN模块的配置在location中,因此须要注冊此函数 */
NULL /* 合并loc配置时的回调 */
};
代码3 配置解析各阶段回调

  绝大多数handler仅仅须要设置最后面回调函数,即:设置ngx_http_xxx_create_loc_conf和ngx_http_xxx_merge_loc_conf.前者用于特定location的内存分配。而后者用来设置默认值以及合并继承过来的配置值,同一时候往往还负责配置值的合法性验证,假设不合法,则退出兴许处理。

3.5 设置模块属性

  NGINX中包括了非常多模块,全部模块都是通过ngx_module_t类型,但每一个模块拥有不同的属性。通过设置各模块不同的属性来控制各模块的行为。LOGIN模块的模块属性设置例如以下:

ngx_module_t ngx_http_login_module =
{
NGX_MODULE_V1, /* 含多个字段:一般使用此宏赋值 */
&ngx_http_login_module_ctx, /* 当前模块上下文回调 */
ngx_http_login_commands, /* 配置指令解析数组 */
NGX_HTTP_MODULE, /* 模块类型 */
NULL, /* 初始化master时的回调 */
NULL, /* 初始化module时的回调 */
NULL, /* 初始化工作进程时的回调 */
NULL, /* 初始化线程时的回调 */
NULL, /* 退出线程时的回调 */
NULL, /* 退出工作进程时的回调 */
NULL, /* 退出master时的回调 */
NGX_MODULE_V1_PADDING /* 含多个字段:一般使用此宏赋值 */
};
代码4 设置模块属性

3.6 编写函数代码

  在代码3中的定义配置解析各阶段的回调设置了创建loc配置时的回调ngx_http_login_create_loc_conf()。其主要功能是为location配置分配内存空间,实现代码例如以下:

/******************************************************************************
**函数名称: ngx_http_login_create_loc_conf
**功 能: 为LOGIN的配置结构分配内存空间
**输入參数:
** cf: 配置信息对象
**输出參数: NONE
**返 回: 存储LOGIN配置的内存地址
**实现描写叙述:
**注意事项:
**作 者: # Qifeng.zou # 2014.05.26 #
******************************************************************************/
static void *ngx_http_login_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_login_loc_conf_t *llcf = NULL; llcf = ngx_palloc(cf->pool, sizeof(ngx_http_login_loc_conf_t));
if(NULL == llcf)
{
return NGX_CONF_ERROR;
} memset(llcf, 0, sizeof(ngx_http_login_loc_conf_t)); return lcf;
}

代码5 创建loc配置时的回调

  在代码1中的定义配置项解析数组中设置了配置项check的回调ngx_http_login_check()。其主要功能解析配置项check。并设置解析后的处理函数,实现代码例如以下:

/******************************************************************************
**函数名称: ngx_http_login_check
**功 能: 配置项check的解析处理回调
**输入參数:
** cf: 配置信息对象
** cmd: 当前正在解析的配置项解析数组
** conf: 自己定义配置结构体ngx_http_login_loc_conf_t的地址
**输出參数: NONE
**返 回: NGX_CONF_OK:Success Other:Failed
**实现描写叙述:
**注意事项:
**作 者: # Qifeng.zou # 2014.05.26 #
******************************************************************************/
static int ngx_http_login_check(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf = NULL; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_login_check_handler;
ngx_conf_set_str_slot(cf, cmd, conf); return NGX_CONF_OK;
}
代码6 CHECK配置项解析处理

  在ngx_http_login_check()中对配置项check进行了解析处理,同一时候设置了解析后的处理函数:ngx_http_login_check_handler()。其主要功能是检測URL中的參数user和passwd的合法性,并返回终于的验证结果。实现代码例如以下:

/******************************************************************************
**函数名称: ngx_http_login_check_handler
**功 能: 验证user和passwd的合法性
**输入參数:
** r: HTTP请求.
**输出參数: NONE
**返 回: 0:Success !0:Failed
**实现描写叙述:
** 1.必须是GET或HEAD请求
** 2.获取LOGIN配置信息
** 3.提取URL參数
** 4.验证URL參数合法性
** 5.发送应答数据
**注意事项:
**作 者: # Qifeng.zou # 2014.05.26 #
******************************************************************************/
static int ngx_http_login_check_handler(ngx_http_request_t *r)
{
ngx_int_t ret = 0;
ngx_str_t user, passwd, repmsg;
ngx_http_login_loc_conf_t *llcf = NULL; /* 1. 必须是GET或HEAD请求 */
if(!(r->method &(NGX_HTTP_GET | NGX_HTTP_HEAD)))
{
return NGX_HTTP_NOT_ALLOWED;
} ret = ngx_http_discard_request_body(r); /* 丢弃请求报文体 */
if(NGX_OK != ret)
{
return ret;
} /* 2. 获取LOGIN配置信息 */
llcf = ngx_http_get_module_loc_conf(r, ngx_http_login_module); /* 3. 提取URL參数
      在网址输入栏输入"localhost/query? user=qifeng&passwd=123456"
则:r->args = "user=qifeng&passwd=123456",因此提取网页參数仅仅需对r->args进行解析就可以. */
query_string(r, &user, "user"); /* 函数:query_string()的功能是从字串r->args中找到相应的參数及值(请自己实现) */
query_string(r, &passwd, "passwd"); /* 4. 验证URL參数合法性 */
if((user.len == llcf->user.len)
&& (0 == strcmp(llcf->user.data, user.data)
&& (passwd.len == llcf->passwd.len)
&& (0 == strcmp(llcf->user.data, passwd.data))
{
ngx_str_set(&repmsg, "Success");
}
else
{
ngx_str_set(&repmsg, "Failed");
} /* 5. 发送应答数据 */
return ngx_http_send_rep(r, &repmsg);
} /******************************************************************************
**函数名称: ngx_http_send_rep
**功 能: 发送应答数据
**输入參数:
** r: Http request.
** repmsg: 应答消息
**输出參数: NONE
**返 回: 0:Success !0:Failed
**实现描写叙述:
** 1.发送应答头
** 2.发送应答体
**注意事项:
**作 者: # Qifeng.zou # 2014.05.26 #
******************************************************************************/
static int ngx_http_send_rep(ngx_http_request_t *r, const ngx_str_t *repmsg)
{
ngx_int_t ret = 0;
ngx_buf_t *b = NULL;
ngx_chain_t out;
ngx_str_t type = ngx_string("text/plain"); /* 1.发送应答头 */
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_type = type;
r->headers_out.content_length_n = repmsg->len; ret = ngx_http_send_header(r);
if((NGX_ERROR == ret) || (ret > NGX_OK) || (r->header_only))
{
return ret;
} /* 2.发送应答体 */
b = ngx_create_temp_buf(r->pool, repmsg->len);
if(NULL == b)
{
return NGX_HTTP_INTERNAL_SERVER_ERROR;
} ngx_memcpy(b->pos, repmsg->data, repmsg->len);
b->last = b->pos + repmsg->len;
b->last_buf = 1; out.buf = b;
out.next = NULL; return ngx_http_output_filter(r, &out);
}
代码7 合法性验证

4 编译project

  Apache, IIS等其它服务器的第三方模块是通过动态链接库的方式增加到程序中。而NGINX的第三方模块须要增加NGINX源代码project一同编译。

  NGINX提供了一种简单的方式将第三方开发的模块编译到NGINX中。首先。将源代码全部放入一个文件夹下,同一时候在该文件夹下创建一个名为config的文件(config的配置格式在4.1节描写叙述);其次,在configure脚本运行时增加參数--add-module=PATH(PATH为第三方模块的源代码路径)。

4.1 编辑编译配置

  完毕以上编辑工作后,最后的工作就是将编写的代码增加NGINXproject。

其处理过程例如以下:

    #cd src/ext/login

    #vim config

    在config文件里输入例如以下内容:

ngx_addon_name=ngx_http_login_module
HTTP_MODULES="$HTTP_MODULES ngx_http_login_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_login_module.c"
代码8 编译配置

  注意:以上config文件里的等号(=)前后不能有空格,否则运行./configure --add-module=src/ext/login时,并不能将login模块增加到project编译环境中.

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlmZW5nem91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" align="middle" />

图2 变量值与等号之间有空格

4.2 增加编译project

  完毕config的编辑后,LOGIN模块还没有增加到编译project中。NGINX的编译脚本比較复杂,功能也十分强大。在编译之前必须告知NGINX编译脚本到指定的路径去增加LOGIN模块:

    #./configure --with-debug --add-module=src/ext/login

    #make

    #make install

4.3 终于測试结果

  输入“localhost/login?user=qifeng&passwd=123456”将会返回成功。

例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlmZW5nem91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
图3 验证成功

  输入“localhost/login?user=zhangsan&passwd=123456”将会返回失败。

例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlmZW5nem91/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
图4 验证失败

NGINX模块开发 之 验证URL參数的更多相关文章

  1. [转] Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  2. 【转】Nginx模块开发入门

    转自: http://kb.cnblogs.com/page/98352/ 结论:对Nginx模块开发入门做了一个helloworld的示例,简单易懂.也有一定的深度.值得一看. Nginx模块开发入 ...

  3. Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  4. Nginx模块开发入门(转)

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  5. Nginx模块开发入门(转)

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

  6. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  7. 解剖Nginx·模块开发篇(1)跑起你的 Hello World 模块!

    1 学习 Nginx 模块开发需要有哪些准备? 需要的预备知识不多,有如下几点: 有过一些 C 语言的编程经历: 知道 Nginx 是干嘛的,并有过编写或改写 Nginx 的配置文件的经历. OK,就 ...

  8. 百度URL參数解析

    百度URL參数解析 在用Python爬取百度搜索的内容时,发现百度搜索的url非常的长.往往会跟一大段的參数,但事实上非常多參数都是没有必要的,如相同是搜索javakeyword,能够通过 http: ...

  9. FW: Nginx模块开发入门

    前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...

随机推荐

  1. JS 基本的介绍

    JS中的注释   HTML的注释:<!—注释内容-->   CSS注释:/* 注释 */   JavaScript的注释:// 或 /*  多行注释 */ 变量 1.变量的概念 变量是变化 ...

  2. PAT甲级——A1109 Group Photo【25】

    Formation is very important when taking a group photo. Given the rules of forming K rows with Npeopl ...

  3. 网络安全系列 之 SQL注入学习总结

    目录 1. sql注入概述 2. sql注入测试工具 3. sql注入防御方法 3.1 问题来源 3.2 防御方法 4. SQL注入防御举例 4.1 使用JDBC时,SQL语句进行了拼接 4.2 使用 ...

  4. 面试系列13 redis都有哪些数据类型

    (1)string 这是最基本的类型了,没啥可说的,就是普通的set和get,做简单的kv缓存 (2)hash 这个是类似map的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象 ...

  5. 全网最全乌云drops文章下载(epub)

    前几天搞得epub格式的,为了方便kindle才做的,没想到站关了. 链接: http://pan.baidu.com/s/1eRIoJC2 密码: b6aq

  6. axios——post请求时把对象obj数据转为formdata格式

    转载自:https://blog.csdn.net/feizhong_web/article/details/80514436  在调用后台接口的时候,上传报名信息,利用axios 的post请求,发 ...

  7. B/S架构及其运行原理

    一. B/S的概念 B/S(Brower/Server,浏览器/服务器)模式又称B/S结构,是Web兴起后的一种网络结构模式.Web浏览器是客户端最主要的应用软件. 这种模式统一了客户端,将系统功能实 ...

  8. PAT甲级——A1086 Tree Traversals Again

    An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example ...

  9. 《DSP using MATLAB》Problem 8.30

    10月1日,新中国70周岁生日,上午观看了盛大的庆祝仪式,整齐的方阵,先进的武器,尊敬的先辈英雄,欢乐的人们,愿我们的 国家越来越好,人民生活越来越好. 接着做题. 代码: %% ---------- ...

  10. 【CF932E】Team Work

    题目 luogu的Romtejudge挂了我就当我过了吧 求 \[\sum_{i=1}^n\binom{n}{i}i^k\] 其实是个思博套路题,但是我现在这个水平还是刷刷板子吧 处理\(x^k\)是 ...