關於nginx_auth_mysql認證模塊
在筆者之前的博文《關於httpd 2.x,mod_auth_mysql模塊的安裝配置以及對aes加密的支持》中,所提及到的mod_auth_mysql模塊,是專門用於Apache httpd的第三方認證模塊。在本文中,將介紹在Nginx上面相對應的一個模塊,nginx_auth_mysql。
準備工作
下載nginx_auth_mysql的源代碼
CentOS7服務器,nginx源碼包(筆者使用nginx1.12.0穩定版)
支持nginx的編譯環境,並安裝有openssl開發包
存在libmysqlclient以及libmysqld動態庫
nginx_auth_mysql的源代碼文件如下所示:
$ ls config crypt_private.c crypt_private.h LICENSE ngx_http_auth_mysql_module.c README
查看一下config配置文件,其內容如下所示:
$ cat config.bak ngx_addon_name=ngx_http_auth_mysql_module HTTP_MODULES="$HTTP_MODULES ngx_http_auth_mysql_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_mysql_module.c $ngx_addon_dir/crypt_private.c" CORE_LIBS="$CORE_LIBS -lcrypto -lmysqlclient" USE_MD5=YES
由上述配置文件的格式,可以看出是專門進行靜態編譯的第三方模塊。由於在Nginx 1.9.11版本之後,已經支持以動態模塊的方式來支持第三方擴展,並且由上述配置文件的內容,初步判定可以將其修改為動態模塊的編譯配置,因此這裏將其編譯為動態庫,以供Nginx進行加載。
關於配置文件的修改以及動靜模塊的轉換,參照如下兩篇文章:
Converting Static Modules to Dynamic Modules
New Config Shell File
經過修改之後的config文件內容如下所示:
ngx_addon_name=ngx_http_auth_mysql_module if test -n "$ngx_module_link"; then ngx_module_type=HTTP ngx_module_name=$ngx_addon_name ngx_module_srcs="$ngx_addon_dir/ngx_http_auth_mysql_module.c $ngx_addon_dir/crypt_private.c" ngx_module_incs="/usr/include/mysql" ngx_module_libs="-lcrypto -lmysqlclient -lmysqld -L/usr/lib64/mysql" . auto/module else HTTP_MODULES="$HTTP_MODULES ngx_http_auth_mysql_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_mysql_module.c $ngx_addon_dir/crypt_private.c" CORE_LIBS="$CORE_LIBS -lcrypto -lmysqlclient" USE_MD5=YES fi
在編譯的時候,添加上--add-dynamic-module
選項,將模塊添加進來。筆者這裏使用的是--add-dynamic-module=/root/nginx-1.12.0/nginx_auth_mysql
,其中的nginx_auth_mysql目錄用於存放模塊的源代碼。
在進行編譯的過程中,筆者遇到了如下錯誤:
/root/nginx-1.12.0/nginx_auth_mysql/ngx_http_auth_mysql_module.c: In function ‘ngx_http_auth_mysql_check_md5’: /root/nginx-1.12.0/nginx_auth_mysql/ngx_http_auth_mysql_module.c:488:19: error: ‘MD5_DIGEST_LENGTH’ undeclared (first use in this function) u_char md5_str[2*MD5_DIGEST_LENGTH + 1]; ^ /root/nginx-1.12.0/nginx_auth_mysql/ngx_http_auth_mysql_module.c:488:19: note: each undeclared identifier is reported only once for each function it appears in /root/nginx-1.12.0/nginx_auth_mysql/ngx_http_auth_mysql_module.c:489:9: error: unused variable ‘md5_digest’ [-Werror=unused-variable] u_char md5_digest[MD5_DIGEST_LENGTH]; ^ /root/nginx-1.12.0/nginx_auth_mysql/ngx_http_auth_mysql_module.c:488:9: error: unused variable ‘md5_str’ [-Werror=unused-variable] u_char md5_str[2*MD5_DIGEST_LENGTH + 1];
從上面的報錯結果來看,可以發現,是MD5_DIGEST_LENGTH沒有定義,甚是奇怪……
經過排查,在ngx_http_auth_mysql_module.c文件裏面,所引用的頭文件當中,似乎確實並未包含MD5_DIGEST_LENGTH的定義,ngx_md5.h的全部內容如下所示:
$ cat ngx_md5.h /* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #ifndef _NGX_MD5_H_INCLUDED_ #define _NGX_MD5_H_INCLUDED_ #include <ngx_config.h> #include <ngx_core.h> typedef struct { uint64_t bytes; uint32_t a, b, c, d; u_char buffer[64]; } ngx_md5_t; void ngx_md5_init(ngx_md5_t *ctx); void ngx_md5_update(ngx_md5_t *ctx, const void *data, size_t size); void ngx_md5_final(u_char result[16], ngx_md5_t *ctx); #endif /* _NGX_MD5_H_INCLUDED_ */
通過對比一個老版本的nginx源代碼,發現確實有所不同,下面的是老版本的nginx的頭文件,可以看出,引用了openssl的md5頭文件定義:
...... ...... #if (NGX_HAVE_MD5) #if (NGX_HAVE_OPENSSL_MD5_H) #include <openssl/md5.h> #else #include <md5.h> #endif ...... ......
通過查閱md5頭文件,得到其定義的值為16,因此,在nginx-1.12.0的ngx_md5.h裏面,添加如下定義:
#define MD5_DIGEST_LENGTH 16
保存之後,重新編譯,成功通過。
編譯完成之後,在objs文件夾裏面生成了所需要的模塊:
$ ls objs/ | grep auth ngx_http_auth_mysql_module_modules.c ngx_http_auth_mysql_module_modules.o ngx_http_auth_mysql_module.so
將ngx_http_auth_mysql_module.so拷貝到對應的模塊目錄裏面,至此完成了初步的模塊安裝任務。
配置內容
在nginx.conf文件中的main段裏面添加如下一行,代表需要加載該模塊:
load_module modules/ngx_http_auth_mysql_module.so;
筆者使用默認主機/auth路徑下的auth.html進行測試:
$ cat /opt/nginx/html/auth/auth.html <h1>auth page</h1>
在該模塊的README文檔中,詳細介紹了模塊使用的配置參數,如下所示:
== CONFIGURATION ==
It is activated by adding several configuration options:
auth_mysql_realm: HTTP basic authentiaction realm. Required.
auth_mysql_host: the host of the MySQL server. Default is 127.0.0.1.
auth_mysql_port: on which port to connect to the MySQL server. Default is 3306.
auth_mysql_user: username for connection to the MySQL server. Default is root.
auth_mysql_password: password for connection to the MySQL server. Default is empty.
auth_mysql_database: name of the database. Required.
auth_mysql_table: name of the table, which holds the user record.
You can have more than one table separated by comas. Default is users.auth_mysql_user_column: name of the username column. Default is username.
auth_mysql_password_column: name of the password column. Default is password.
auth_mysql_conditions: Additional SQL conditions. They will be placed after and AND.
Default is empty string.auth_mysql_group_table: name of the table, which holds the groups information.
You can have more than one table separated by comas. Default is the users table.auth_mysql_group_column: name of the group name column. Default is name.
auth_mysql_group_conditions: Additional SQL conditions applied only in group queries.
They will be placed after an AND. Default is empty string.auth_mysql_encryption_type: the format of the password field. Should be one of:
none: the password is stored in plaintext in the database;
md5: in the database is stored a md5 hash of the password;
phpass: a portable php hash of the password is stored. See:
http://www.openwall.com/phpass/ for more information.
The default is md5.auth_mysql_allowed_users: whitespace delimited list of allowed users.
auth_mysql_allowed_groups: whitespace delimited list of allowed groups.
If both allowed_users and allowed_groups are defined, either of them has to satisfied.
筆者這裏使用mysql數據庫創建認證用戶的內容如下所示,創建nginx數據庫,在nginx數據庫裏面添加一個nginx_auth的數據表,存放user字段和password字段,並且password字段用md5進行加密:
$ mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 3337 Server version: 5.5.44-MariaDB MariaDB Server Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others. Type ‘help;‘ or ‘\h‘ for help. Type ‘\c‘ to clear the current input statement. MariaDB [(none)]> use nginx; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed MariaDB [nginx]> show tables; +-----------------+ | Tables_in_nginx | +-----------------+ | nginx_auth | +-----------------+ 1 row in set (0.00 sec) MariaDB [nginx]> select * from nginx_auth; +------+----------------------------------+ | user | password | +------+----------------------------------+ | tom | d077f244ddf8r70e5ea758bd8352fcd8 | +------+----------------------------------+ 1 row in set (0.00 sec)
在nginx.conf配置文件當中使用的配置如下所示:
...... ...... location /auth { root /opt/nginx/html; index auth.html; auth_mysql_realm "authentication"; auth_mysql_host "192.168.5.181"; auth_mysql_port "3306"; auth_mysql_user "nginx"; auth_mysql_password "nginx"; auth_mysql_database "nginx"; auth_mysql_table "nginx_auth"; auth_mysql_user_column "user"; auth_mysql_password_column "password"; auth_mysql_encryption_type "md5"; } ...... ......
reload一下nginx,利用curl命令進行測試,得到的結果如下所示,可見模塊正常運行:
$ curl -u tom:right_password http://192.168.5.181/auth/ <h1>auth page</h1> $ curl -u tom:wrong_password http://192.168.5.181/auth/ <html> <head><title>401 Authorization Required</title></head> <body bgcolor="white"> <center><h1>401 Authorization Required</h1></center> <hr><center>nginx/1.12.0</center> </body> </html>
其他事項
在httpd上面使用的mod_auth_mysql模塊,自帶了aes加密算法,但是在nginx上面使用的此模塊,默認卻沒有添加該項功能,不過該模塊的作者在README中提到:
== WRITING A NEW ECNRYPTION TYPE ==
Add an entry in thengx_http_auth_mysql_enctypes
array. It has to be a struct
with two elements:
ngx_str_t id
The name under which it should be referenced in the config file
ngx_uint_t (*checker)(ngx_http_request_t *r, ngx_str_t sent_password, ngx_str_t actual_password)
A function, which given the request (mostly used for logging and memory allocation through its r->pool),
the password sent by the user and the password in the database has to determine whether they match.
If they match it should return NGX_OK, if they don’t it should return NGX_DECLINED. If other error
occures, it should log it and return NGX_ERR.Currently salts aren‘t supported, but if there are schemes, which require them it is quite easy.
Questions/patches may be sent to Nikolay Bachiyski, [email protected]
似乎只能等待牛人進行二次開發了......
本文出自 “技術成就夢想” 博客,請務必保留此出處http://jiangche00.blog.51cto.com/4377920/1941560
關於nginx_auth_mysql認證模塊