HTTP Session模块
目录 |
HTTP Session模块
概要
Session模块提供了对HTTP请求的跟踪功能,其他的一些安全模块会依赖于此模块进行一些处理。
Session会在客户端的浏览器设置一个Cookie用于记录会话信息。
目前依赖于session功能的模块有:
- Cookie防篡改
命令
session
语法 | session on/off |
默认值 | off |
上下文 | Server |
开启或关闭session功能。
举例:
session on;
session_timeout
语法 | session_timeout timeout |
默认值 | 60 |
上下文 | Server |
设置session的超时时间,单位是秒。
举例:
session_timeout 600;
session_max_size
语法 | session_max_size number |
默认值 | |
上下文 | HTTP |
设定session的最大数量;
举例:
session_max_size 10000;
session_cookie_name
语法 | session_cookie_name name |
默认值 | SENGINX-SESSION-ID |
上下文 | HTTP/Server/Location |
设置session cookie的名称;
举例:
session_cookie_name session-id;
session_blacklist_timeout
语法 | session_blacklist_timeout timeout |
默认值 | session_timeout值 |
上下文 | HTTP/Server/Location |
设置基于session的黑名单的超时时间,单位是秒,此时间不能小于session timeout的数值。
举例:
session_blacklist_timeout 600;
session_redirect_timeout
语法 | session_redirect_timeout timeout |
默认值 | 5 |
上下文 | HTTP/Server/Location |
设置SEnginx发送redirect响应后的等待时间,单位是秒。
举例:
session_redirect_timeout 600;
session_show
语法 | session_show on/off |
默认值 | off |
上下文 | Location |
显示当前所有的session信息;此location所在的server必须开启session功能。
可以使用浏览器直接访问这个location以查看session信息。
举例:
location /show_session { session_show on; }
使用Session API开发模块
session模块提供了一组函数,用于其他依赖于session的模块使用。session本质上是一个数据的存储点,其他模块可以将一些数据存储到session节点上,然后在本模块处理request的时候对这些数据进行操作,主要的API如下表所示:
void * ngx_http_session_shm_alloc(size_t size); void ngx_http_session_shm_free(void *); void * ngx_http_session_shm_alloc_nolock(size_t size); void ngx_http_session_shm_free_nolock(void *); ngx_http_session_ctx_t * ngx_http_session_create_ctx(ngx_http_session_t *session, u_char *name, ngx_int_t (*init)(void *ctx), void (*destroy)(void *data)); ngx_http_session_ctx_t * ngx_http_session_find_ctx(ngx_http_session_t *session, u_char *name); void ngx_http_session_destroy_ctx(ngx_http_session_t *session, u_char *name); ngx_http_session_t * ngx_http_session_get(ngx_http_request_t *r); void ngx_http_session_put(ngx_http_request_t *r); ngx_int_t ngx_http_session_is_enabled(ngx_http_request_t *r); void ngx_http_session_register_create_ctx_handler(ngx_http_session_create_ctx_t handler);
现举例说明这些API的用法
注册创建ctx的回调函数
首先要在模块的初始化阶段向session模块注册创建ctx的回调函数, 此回调函数会被在一个新session建立的时候调用,用于创建ctx. 例如,在cookie poisoning模块中,需要先注册ctx的回调函数
static ngx_int_t ngx_http_cp_filter_init(ngx_conf_t *cf) { ngx_int_t ret; ret = ngx_http_neteye_security_header_register( NGX_HTTP_NETEYE_COOKIE_POISONING, ngx_http_cp_header_handler); if (ret == NGX_ERROR) { return NGX_ERROR; } ngx_http_session_register_create_ctx_handler( ngx_http_cp_create_session_ctx); return ngx_http_neteye_security_request_register( NGX_HTTP_NETEYE_COOKIE_POISONING, ngx_http_cp_handler); }
其中,ngx_http_cp_create_session_ctx的典型实现为:
static void ngx_http_cp_create_session_ctx(ngx_http_session_t *session) { ngx_http_session_ctx_t *session_ctx; ngx_http_cp_session_ctx_t *cp_ctx; session_ctx = ngx_http_session_create_ctx(session, (u_char *)"cookie_poisoning", ngx_http_cp_init_session_ctx_handler, ngx_http_cp_destroy_session_ctx_handler); if (!session_ctx) { return; } /* init cp_ctx */ cp_ctx = session_ctx->data; cp_ctx->bl_times = 0; ngx_http_cp_hash_init(&cp_ctx->monitored_cookies, NGX_HTTP_CP_DEFAULT_BUCKETS_NUM); }
使用session存储数据的方法
1. 首先需要获取session结构体:
session = ngx_http_session_get(r);
2. 然后再进行其他操作之前,对这个session加锁:
ngx_shmtx_lock(&session->mutex);
3. 从session中提取之前保存的信息,session上保存的信息是每个模块自己存放的ctx结构:
session_ctx = ngx_http_session_find_ctx(session, action->session_name);
- ctx结构是模块自行创建,并保存到session上的,ctx结构以名字为唯一标识
4. 对取出的ctx进行需要的操作以完成模块的特定功能
5. 当不在需要使用ctx中存储的内容时,需要解锁session,并减小引用计数:
ngx_shmtx_unlock(&session->mutex); ngx_http_session_put(r);
ngx_http_session_create_ctx中的init函数和destroy函数的写法
可以参考robot mitigation的init函数和destroy函数:
static void ngx_http_rm_destroy_ctx_handler(void *ctx) { ngx_http_session_ctx_t *session_ctx; session_ctx = (ngx_http_session_ctx_t *)ctx; return ngx_http_session_shm_free_nolock(session_ctx->data); } static ngx_int_t ngx_http_rm_init_ctx_handler(void *ctx) { ngx_http_session_ctx_t *session_ctx; session_ctx = (ngx_http_session_ctx_t *)ctx; /* initial session ctx */ session_ctx->data = ngx_http_session_shm_alloc_nolock(sizeof(ngx_http_rm_session_ctx_t)); if (!session_ctx->data) { fprintf(stderr, "create ac ctx error\n"); return NGX_ERROR; } memset(session_ctx->data, 0, sizeof(ngx_http_rm_session_ctx_t)); return NGX_OK; }
在共享内存区域分配内存,需要使用ngx_http_session_shm_alloc/free系列函数