ngx_lua實現登陸邏輯

最近在公司作一個簡單的portal,原本很簡單的,只用ngx_lua就能夠實現全部的業務邏輯,不須要upstream上游服務。但被要求接入公司內部的用戶校驗系統,說白了就是一個登陸過程,只容許公司內部的用戶能夠登陸訪問。php

公司內部有一整套組件,只要在業務代碼裏嵌入改組件,就能自動檢測用戶是否已經登陸、或session是否過時,是則跳轉到登陸界面,用戶輸入密碼驗證後,從新跳轉會原始訪問的頁面。java

但公司提供的組件都是基於經常使用的業務語言的,如php、java,我也不想再加上這些玩意,因而考慮用ngx_lua實現這樣一套登陸邏輯。下面是一個測試配置,基本總結了nginx中實現登陸的方法。nginx

    lua_shared_dict stats 10m;
        init_by_lua '
                local stats = ngx.shared.stats
                stats:set("flag",1)
        ';

    server {
                listen 80 so_keepalive=on;

                set $flag 0;
                rewrite_by_lua '
                        local stdo = string.match(ngx.var.uri, "(%a+%.do)")
                        if stdo == nil then
                                local res = ngx.location.capture("/isLoginExpired.do")
                                ngx.var.flag = res.body
                        end
                ';

                location /isLoginExpired.do {
                        content_by_lua '
                                local stats = ngx.shared.stats
                                local flag = stats:get("flag")
                                ngx.print(flag)
                        ';
                }

        location / {

                  content_by_lua '
                        if ngx.var.flag == "1" then
                                local query = "backuri="..ngx.var.request_uri
                                query = string.gsub(query,"&","%%26")
                                return ngx.redirect("/redirect?"..query, 302) 
                        else
                                local new_uri = "/fcgi"..ngx.var.request_uri
                                ngx.exec("/fcgi")
                        end
                  ';

        }

                location /redirect {
                        content_by_lua '
                                local stats = ngx.shared.stats
                --      do login or update cookies, and then flag=0
                                stats:set("flag",0)
                                local backuri = ngx.var.arg_backuri
                                return ngx.redirect(backuri, 302)
                        ';
                }

                location /fcgi {
                        content_by_lua '
                                ngx.say(ngx.var.request_uri)
                                ngx.say("come into fcgi")
                                ngx.say(ngx.var.flag)
                                ngx.say(ngx.var.right)
                        '; 
                }

    }

 

這裏用共享內存 stats:flag模擬是否登陸的標誌位,初始爲1,表示未登陸。cookie

對於全部請求,首先用一段rewrite_by_lua代碼來判斷是否登陸,這裏主要就是查看stats:flag的值,其中能夠利用ngx_lua提供的強大的子請求功能。這裏要注意的是,所用子請求的uri必定要排除在要判斷登陸態請求以外(即該/isLoginExpired.do請求不能再去判斷登陸態,不然會形成死循環)。session

以後全部請求進入 location / {...},這裏主要利用前面判斷的結果(ngx.var.flag的值,不要和那個stats:flag混淆了,名字沒起好),沒有登陸,則利用ngx.redirect()作302跳轉,跳轉到登陸界面,用戶能夠輸入密碼,這裏簡單的模擬了一下,直接把stats:flag置0,而且添加query語句,帶上backuri字段。測試

通常登陸應用中,都會讀取backuri字段,登陸認證後,從新302到該backuri。例子中的location /redirect {...} 就是模擬了這樣一個登陸應用。lua

請求從新來以後,進入location / {...}, 判斷已登陸,則經過ngx.exec()直接內部跳轉到具體的業務location。spa

 

一開始的時候仍是以爲比較繞的,理清楚以後仍是比較簡潔的,這裏面用到ngx_lua的幾個強大的功能,也是一次很好的實踐code

ngx.location.capture()    子請求server

ngx.redirect()        等同於nginx原生的rewrite .. .. redirect (302跳轉)

ngx.exec()           等同於nginx原生的rewrite .. .. break (內部跳轉)

 

運行結果以下

 

 

不當之處,歡迎指正

相關文章
相關標籤/搜索