• nginx的http模块开发一个验证url参数的例子


    本文开发一个nginx http模块基本的开发步骤和前篇http://www.cnblogs.com/yjf512/archive/2013/06/10/3130890.html 说的一样,按照开发的六个步骤写。

    配置文件及功能

    该模块的功能是验证请求url中的secret参数的值是否是约定的秘钥。

    它的nginx配置文件是这样的:

    worker_processes  1;
    
    error_log logs/error.log debug;
    master_process off;
    daemon off;
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        default_type  application/octet-stream;
    
        sendfile        on;
    
        keepalive_timeout  65;
    
        server {
            listen       8001;
            server_name  localhost;
    
            access_log  /tmp/access.log; 
            error_log  /tmp/error.log debug;
    
            location / {
                root   html;
                index  index.html index.htm;
            }
    
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            location = /mysecert {
                # 只有传递的secret参数值为secretpassword的时候才通过验证
                # 1 通过验证页面显示“secret right”
                # 2 不通过验证页面显示“secret wrong”
                # 比如
                # http://abc.com:8001?secret=secretpassword通过
                # http://abc.com:8001?secret=123不通过
                mysecret secretpassword;
            }
        }
    
    }

    location为/mysecret的时候,需要传递值为secretpassword的mysecret参数。页面会返回200并显示secret right,否则页面返回200并显示secret wrong。

    配置文件这里有几个地方注意下:

    为了调试方便,调整了几个地方:

    worker_processes  1; 
    master_process off;
    daemon off;
    …
    access_log  /tmp/access.log; 
    error_log  /tmp/error.log debug;

    而且在configure的时候我也加上了--with-debug参数

    ./configure --add-module=/home/yejianfeng/nginx/nginx_module/mysecret2/ --prefix=/home/yejianfeng/nginx/nginx/ --with-debug 

    这样让调试更加方便

    具体代码

    完整的代码可以看:https://github.com/jianfengye/MyWorks/tree/master/nginx_module_mysecret

    有几个地方要说明:

    1 这个模块由于有从配置文件中读取的信息,所以它是有属于自己模块的配置文件结构的

    typedef struct {
    
         ngx_str_t secret;
    
    } ngx_http_mysecret_conf_t;

    所以有自己的配置文件,那么在模块构造模块上下文的时候create_loc_conf的阶段就多一个功能是初始化配置文件结构

    // 定义上下文, 只会在location中出现,所以都为null

    static ngx_http_module_t ngx_http_mysecret_module_ctx = {

         NULL,

         NULL,

         NULL,

         NULL,

         NULL,

         NULL,

         ngx_http_mysecret_create_loc_conf,  //这里有使用自己的配置结构

         NULL

    };

    其中ngx_http_mysecret_create_loc_conf只要做的事情是初始化配置文件

    2 如何将配置文件nginx.conf中的mysecret的一个参数放在配置文件结构中呢?

    在ngx_http_mysecret这个命令回调函数中,有个ngx_conf_set_str_slot,这个是nginx预设的14个读取配置文件的函数之一,调用它就可以把nginx.conf中的secrect秘钥读取到配置文件结构中了。

    3 在handler中怎么获取配置文件结构呢?

    现在读取配置文件结束了,也构造了配置文件结构,到具体的处理http请求的阶段,如何获取这个结构呢?

    ngx_http_mysecret_conf_t *mycf;
    
    mycf = ngx_http_get_module_loc_conf(r, ngx_http_mysecret_module);

    使用这个方法就能在handler中获取到自定义的配置文件结构了。

    获取配置结构后,后面的问题就是如何获取请求参数呢

    ngx_http_request_t中的args参数就是获取请求参数的

    比如http://abc.com?a=s&b=2 那么args就是ngx_string("a=s&b=2")

    后面就可以使用nginx自定义的ngx_strncasecmp进行字符比较等操作了。

    好了,完整的一个验证请求参数的模块就写完了。

    模块变种

    有人会对nginx.conf文件有点不舒服,可能希望设置验证秘钥是分为两个步骤:

    设置秘钥和验证秘钥

    即配置文件大致变成现在的样子:

    location = /mysecert {
                # 只有传递的secret参数值为secretpassword的时候才通过验证
                # 1 通过验证页面显示“secret right”
                # 2 不通过验证页面显示“secret wrong”
                # 比如
                # http://abc.com:8001?secret=secretpassword通过
                # http://abc.com:8001?secret=123不通过
                setmysecret secretpassword;
                checksecret;
     }

    原来的mysecret被两个命令setmysecret和checksecret替换了

    这两个命令的功能其实是不一样的,setmysecret只是读取配置文件,并不会对请求做任何操作,而checksecret是直接修改请求的。

    其实上一个例子稍微改一改就可以达到这样的目的:

    https://github.com/jianfengye/MyWorks/tree/master/nginx_module_mysecret2

    定义模块命令的结构就变成:

    static ngx_command_t ngx_http_mysecret_commands[] = {
         {
              ngx_string("setmysecret"),
              NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
              ngx_conf_set_str_slot,
              NGX_HTTP_LOC_CONF_OFFSET,
              offsetof(ngx_http_mysecret_conf_t, secret),
              NULL,
         },
         {
              ngx_string("checksecret"),
              NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
              ngx_http_mysecret,
              NGX_HTTP_LOC_CONF_OFFSET,
              0,
              NULL,
         },
    
         ngx_null_command
    };

    这里的setmysecret直接使用nginx预设的ngx_conf_set_str_slot方法,它就不需要有任何定义handler的操作了。事实上,nginx很多模块的像setmysecret这样的读取配置文件的命令(不做任何http请求的操作)都是直接使用nginx预设的14种方法的。具体的使用在《深入理解Nginx》第四章中有详细说明了。

    自然在checksecret命令中就不需要再读取参数了(也没有参数了,所以要注意这个命令中的命令类型要设置上NGX_CONF_NOARGS)

    实时了解作者更多技术文章,技术心得,请关注微信公众号“轩脉刃的刀光剑影”

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

  • 相关阅读:
    SQL 启动服务方法
    SQL 2012 连接失败
    数据库 基本操作有哪些
    windows 计算机 管理 命令
    windows下编译使用NDK,调用SO文件
    windows 注册表命令
    spring @Transactional 声明式事务
    Set List Map
    bean 的各个属性
    util:
  • 原文地址:https://www.cnblogs.com/yjf512/p/3133569.html
Copyright © 2020-2023  润新知