07_Nginx_auth_request模块

1. auth_request模块是什么

ngx_http_auth_request_module模块(1.5.4+)实现了基于一子请求的结果的客户端的授权。如果子请求返回2xx响应码,则允许访问。如果它返回401或403,则访问被拒绝并显示相应的错误代码。子请求返回的任何其他响应代码都被认为是错误的。

auth_request使用的也是subrequest进行子请求。

2. auth_request模块的用途

如图,当我们访问一个资源需要进行鉴权时,可以使用Nginxhttp_auth_request_module模块进行处理
在这里插入图片描述

3. auth_request的启用

--with-http_auth_request_module
configure阶段使用该命令进行添加

4. auth_request的官方示例

location /private/ {
    auth_request /auth;
    # 此处之后可以填资源服务器的地址,表示健全成功后继续访问的资源
    ...
}

location = /auth {
    # 此处填鉴权服务器的地址
    proxy_pass ...																			
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

5. 源码欣赏

5.1 结构体

源码路径src/http/modules/ngx_http_auth_request_module.c

typedef struct {
    ngx_str_t                 uri;                  		// 子请求的url地址
    ngx_array_t              *vars;                  // 子请求url中的参数
} ngx_http_auth_request_conf_t;			//用于存储在配置文件中的url地址


typedef struct {
    ngx_uint_t                done;                 				// 标记子请求是否完成
    ngx_uint_t                status;               				// 标记子请求响应的状态码
    ngx_http_request_t       *subrequest;         		// 指向子请求的指针
} ngx_http_auth_request_ctx_t;                      	// auth_request模块上下文

5.2 相关函数

/**
 * @brief auth_request的handle函数
 * 
 * @param r 
 * @return ngx_int_t 
 */
static ngx_int_t
ngx_http_auth_request_handler(ngx_http_request_t *r)
{
    ngx_table_elt_t               *h, *ho;          // nginx的一个表结构,key-value
    ngx_http_request_t            *sr;              // 子请求
    ngx_http_post_subrequest_t    *ps;              // 子请求结束时的回调结构体,可注册回调函数
    ngx_http_auth_request_ctx_t   *ctx;             // 父请求上下文,可保存一些信息
    ngx_http_auth_request_conf_t  *arcf;            // auth_request在conf中的配置信息

    // 从conf文件中获取auth_request的配置信息
    arcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_request_module);

    if (arcf->uri.len == 0) {                       // 如果没有配置此模块的命令,则返回NGX_DECLINED
        return NGX_DECLINED;
    }

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "auth request handler");

    // 获取父请求的上下文,
    ctx = ngx_http_get_module_ctx(r, ngx_http_auth_request_module);

    if (ctx != NULL) {                              // 父请求第n+1次数 进入ngx_http_auth_request_handler函数
        if (!ctx->done) {                           // 如果子请求没完成,那么返回NGX_AGAIN,告诉Nginx还需要等待网络事件的完成
            return NGX_AGAIN;
        }

        /*
         * as soon as we are done - explicitly set variables to make
         * sure they will be available after internal redirects
         */

        if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) {
            return NGX_ERROR;
        }

        /* return appropriate status */
        // 子请求结束了
        
        if (ctx->status == NGX_HTTP_FORBIDDEN) {    // 返回403
            return ctx->status;
        }

        if (ctx->status == NGX_HTTP_UNAUTHORIZED) { // 如果是401没有鉴权错误,则获取子请求的响应头中的鉴权信息,添加到父请求的响应头中去

            sr = ctx->subrequest;

            h = sr->headers_out.www_authenticate;

            if (!h && sr->upstream) {
                h = sr->upstream->headers_in.www_authenticate;
            }

            if (h) {
                ho = ngx_list_push(&r->headers_out.headers);
                if (ho == NULL) {
                    return NGX_ERROR;
                }

                *ho = *h;

                r->headers_out.www_authenticate = ho;
            }

            return ctx->status;
        }

        // 子请求鉴权通过返回正确资源 
        if (ctx->status >= NGX_HTTP_OK
            && ctx->status < NGX_HTTP_SPECIAL_RESPONSE)
        {
            return NGX_OK;
        }

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "auth request unexpected status: %ui", ctx->status);

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    // 父请求第一次进入ngx_http_auth_request_handler函数
    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t));
    if (ctx == NULL) {
        return NGX_ERROR;
    }

    // 初始化子请求结束回调结构体
    ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
    if (ps == NULL) {
        return NGX_ERROR;
    }

    ps->handler = ngx_http_auth_request_done;
    ps->data = ctx;

    // 发起子强求
    if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps,
                            NGX_HTTP_SUBREQUEST_WAITED)
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    /*
     * allocate fake request body to avoid attempts to read it and to make
     * sure real body file (if already read) won't be closed by upstream
     */

    sr->request_body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
    if (sr->request_body == NULL) {
        return NGX_ERROR;
    }

    // 子请求返回时只包含相应头信息
    sr->header_only = 1;

    // 父请求上下文记录子请求的指针
    ctx->subrequest = sr;

    // 保存父请求上下文
    ngx_http_set_ctx(r, ctx, ngx_http_auth_request_module);

    return NGX_AGAIN;
}

/**
 * @brief 子请求结束时调用的函数
 * 
 * @param r 
 * @param data 
 * @param rc 
 * @return ngx_int_t 
 */
static ngx_int_t
ngx_http_auth_request_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
{
    ngx_http_auth_request_ctx_t   *ctx = data;              // 获取父请求的上下文  

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "auth request done s:%ui", r->headers_out.status);

    ctx->done = 1;                                          // 标记子请求完成且记录子请求额响应头信息
    ctx->status = r->headers_out.status;

    return rc;
}



  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
要在Nginx中添加http_auth_request_module模块,你可以按照以下步骤操作: 1. 确认你的Nginx版本是否支持http_auth_request_module模块。你可以使用以下命令来检查: ``` nginx -V ``` 在输出结果中查找是否包含 "--with-http_auth_request_module" 字样,如果有,说明该模块已经被支持。 2. 如果你的Nginx版本不支持该模块,你需要重新编译Nginx并启用该模块。首先,下载Nginx的源代码: ``` wget http://nginx.org/download/nginx-x.x.x.tar.gz ``` (将 "x.x.x" 替换为你想要下载的版本号) 3. 解压源代码包: ``` tar -zxvf nginx-x.x.x.tar.gz ``` 4. 进入解压后的目录: ``` cd nginx-x.x.x ``` 5. 执行以下命令进行配置,确保启用了http_auth_request_module模块: ``` ./configure --with-http_auth_request_module ``` 6. 执行以下命令编译并安装Nginx: ``` make sudo make install ``` 7. 配置Nginx的配置文件(通常是位于 /etc/nginx/nginx.conf)。在合适的位置添加以下配置项: ``` location / { auth_request /auth; ... } location = /auth { internal; proxy_pass http://auth_backend; ... } ``` 这里的 "/auth" 是用来处理认证请求的URL,你可以根据需要进行修改。"http://auth_backend" 是实际处理认证请求的后端服务地址,也需要根据实际情况进行修改。 8. 保存并关闭配置文件后,重启Nginx服务: ``` sudo service nginx restart ``` 现在,你已经成功地添加了http_auth_request_module模块Nginx中。你可以根据实际需求进一步配置和使用该模块来进行认证授权操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fantongl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值