使用場景
需要在后端服務之前做訪問控制,或沒有后端服務的場景,如靜態文件。
實驗環境
Ubuntu 14.04
Nginx 1.4.6
安裝 Lua 運行環境
sudo apt-get install lua5.1 liblua5.1-dev liblua5.1-socket2 libluajit-5.1-2 libluajit-5.1-common nginx-extras
測試是否支持 lua
在 Nginx server 配置中增加location塊:
location /lua/test/ { default_type 'text/html'; content_by_lua 'ngx.say("hello world");'; }
能看到對應瀏覽器輸出,表示當前Nginx已支持lua腳本:
簡單的簽名驗證
舉例實現對某個靜態文件目錄添加簽名驗證。
URL參數包含當前時間戳“ts”,以及簽名“sign”,lua腳本實現以下功能:
- 時間戳與當前服務器時間相差上下5分鍾以內。
- 使用secretkey+時間戳做MD5,得到簽名字符串,與傳入的sign參數對比驗證。
- 如果以上任何一個驗證不通過,則返回403錯誤。
代碼如下:
location /lua/tmp/ { alias /tmp/; access_by_lua ' -- 配置的app id對應secret key local appIdKeys = { ["app001"] = "secretkey_1", ["app002"] = "secretkey_2" }; local args = ngx.req.get_uri_args(); local timestamp = args["timestamp"]; -- 獲取參數的時間戳 local now = os.time(); -- 獲取當前時間戳 local offset = math.abs(now - timestamp); -- 計算時間差絕對值 -- 時間戳相差超過300秒,返回403 if offset > 300 then ngx.status = ngx.HTTP_FORBIDDEN; ngx.say("403 Forbidden<br>"..now); ngx.exit(ngx.HTTP_FORBIDDEN); end local appid = args["appid"]; -- 參數中的APP ID local sign = args["sign"]; -- 參數中的簽名 local curr_sign = ngx.md5(appIdKeys[appid] .. timestamp); -- 如果參數中的 sign 和計算得到的 curr_sign 不相等,則說明訪問非法,禁止訪問,否則放行訪問 if curr_sign ~= sign then ngx.status = ngx.HTTP_FORBIDDEN; ngx.say("Invalid signature"); ngx.exit(ngx.HTTP_FORBIDDEN); end '; }
執行結果:
多說兩句
配合 lua-nginx-redis 模塊,能夠讀取redis數據,實現更豐富的驗證手段。