版权声明:本文为博主原创文章,未经博主同意不得转载。 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. csdn的富文本编辑器(html)格式的文章,添加的代码格式粘贴到项目中总是不对,我这里是maven的pom文件。

    在用富文本编辑器(html)格式编辑的时候,总是出现将pom文件的配置从csdn粘贴到项目中发现很多红,是因为自己在设置的时候有问题. 因为我们的是pom.xml,这里原来设置的java呀或者js为了 ...

  2. IENumerable_Test

    using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...

  3. 左神算法进阶班1_1添加最少字符得到原字符N次

    Problem: 给定一个字符串str1,只能往str1的后面添加字符变成str2. 要求1:str2必须包含两个str1,两个str1可以有重合,但是不能以同一个位置开头. 要求2:str2尽量短最 ...

  4. 初识OpenCV-Python - 003:Mouse as a paint-brush

    此次学习了如何在OpenCV中使用鼠标事件.主要使用cv2.setMouseCallback()函数来调用鼠标事件. 首先,鼠标有如下事件: >>> import cv2>&g ...

  5. python字符串的索引切片和常用操作方法,for循环

    ---恢复内容开始--- 一.字符串的索引与切片 1.索引 s = 'ASDFGHJKL' 有序序列,索引--index:从0开始 s1 = s[0],取出单个元素:A: s1是个全新的字符串和原字符 ...

  6. vue 计算属性实现过滤关键词

    效果 html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <m ...

  7. linux常用软连接使用ln -s

    [软连接]另外一种连接称之为符号连接(Symbolic Link),也叫软连接.软链接文件有类似于Windows的快捷方式.它实际上是一个特殊的文件.在符号连接中,文件实际上是一个文本文件,其中包含的 ...

  8. 关于Mysql几周的整理文档

    https://files.cnblogs.com/files/swobble/mysql.rar 内容包括 版本测试(5.5,5.6,5.7) 平台测试(windows所有平台) 文件说明 精简说明 ...

  9. 区间dp——cf1025D二叉搜索树的中序遍历好题!

    这题帮我复习了一下BST的中序遍历.. 因为给定的数组是递增的,那么BST的中序遍历一定是1 2 3 4 5 6 7 8 9 ... n 即[l,r]为左子树,那么根节点就是r+1,反之根节点就是l- ...

  10. Java +支付宝 +接入

    说下业务场景, 公司之前的支付宝业务是PHP对接的现在改成 Java ,在接入出现不同的问题.之前PHP用的是老的移动支付, 现在Java的新接口 , 需要签约. 跟运维沟通好几次, 说签约不了, 只 ...