nginx的basic auth配置由ngx_http_auth_basic_module模塊提供,對HTTP Basic Authentication協議進行了支持,用戶可通過該配置設置用戶名和密碼對web站點進行簡單的訪問控制。
basic auth配置示例:
location / { auth_basic "closed site"; auth_basic_user_file conf/htpasswd;}
說明:
auth_basic可設置為off或其它字符串,為off時表示不開啟密碼驗證 auth_basic_user_file 為包含用戶名和密碼的文件,文件內容如elastic:YsEm9Tb4.RwB6踩坑的地方就是這個密碼,官方文檔里對支持的密碼類型進行了說明:
采用系統函數crypt()加密的密碼;可通過htpasswd命令或者openssl passwd命令生成 通過Apache提供的基于MD5的變種加密算法(apr1),同樣可通過htpasswd或者openssl passwd命令生成 以“{scheme}data”格式表示的加密后的密碼,RFC 2307中有對該格式的密碼標準進行了說明。其中scheme指的是加密算法,nginx支持的scheme有PLAIN, SHA,SSHA算法。使用htpasswd或者openssl passwd命令生成的密碼固然可以使得配置生效,nginx能夠正常地進行密碼安全校驗,如果密碼類型不支持, 則nginx或報錯:
crypt_r() failed (22: Invalid argument)
但是因為業務的需要,我們要用代碼生成nginx的配置并下發配置到每個云主機中,之后拉起nginx進程。項目代碼使用go語言編寫,所以需要找一個對應的函數或者庫生成nginx支持的密碼。
go語言生成nginx支持的密碼
在進行自動生成密碼開發之前,思考了一下大概有三種方案可以實現:
項目服務器上安裝htpasswd工具或openssl, 通過代碼執行本地命令生成加密密碼 直接調用Linux系統函數crypt()加密密碼 使用go標準庫crypto加密密碼首先,第一種方式是不太可取的,因為需要強依賴服務器環境,所以直接pass。下面看第二種和第三種方式的具體實現。
直接調用系統函數crypt()
Linux的crypt函數有兩個參數,函數定義為:
char *crypt(const char *key, const char *salt);
其中參數key為需要加密的內容,salt參數有兩種類型:
長度為2的字符串,取值范圍為[a-zA-Z0-9./],如果超過兩位會被忽略,并且只能支持最長8位的key,如果key超過8位,則8位之后的會被忽略 $id$salt$encrypted 格式,用于支持其它的加密算法, id表示算法類型,具體取值有:ID | Method ───────────────────────────────────────────── 1 | MD5 2a | Blowfish (not in mainline glibc; added in some | Linux distributions) 5 | SHA-256 (since glibc 2.7) 6 | SHA-512 (since glibc 2.7)
go語言中可以通過import "C"方式直接調用c語言的庫函數,下面是封裝crypt函數的具體實現:
package crypt/*#define _GNU_SOURCE#include <unistd.h>*/import "C"import ( "sync" "unsafe")var ( mu sync.Mutex)func Crypt(pass, salt string) (string, error) { c_pass := C.CString(pass) defer C.free(unsafe.Pointer(c_pass)) c_salt := C.CString(salt) defer C.free(unsafe.Pointer(c_salt)) mu.Lock() c_enc, err := C.crypt(c_pass, c_salt) mu.Unlock() if c_enc == nil { return "", err } defer C.free(unsafe.Pointer(c_enc)) return C.GoString(c_enc), err}
新聞熱點
疑難解答