經過Nginx的auth_request以及ExpressJS構建權限驗證系統

本文的內容是個人開源代碼(https://github.com/e10101/AdminLogin)的中文說明。
項目主要是實現了經過合理配置Nginxauth_request模塊來實現對敏感路徑下的內容進行訪問限制。javascript

代碼

可經過Github訪問:https://github.com/e10101/AdminLogin,來獲取代碼。若是能夠的話,能夠Star一下。java

開發初衷

這個項目是爲了解決網站中部分管理資源(路徑)須要進行權限限制,但又不想經過複雜系統去實現而進行編寫的項目.nginx

同時這個項目也沒有采用Nginxauth_basic模塊來實現權限限制.二是經過auth_request來進行的權限限制.git

結構框架

本項目是基於NodeJS/ExpressJS/PassportJS以及Github的。github

爲講解方便,假設存在:
服務器A(server1.example.com),其路徑/installs上存有敏感信息,其餘路徑可公開訪問,端口3003。
服務器B(login.example.com),爲認證服務器,其上部署了本項目代碼,端口4001。瀏覽器

系統以CentOS7.2爲例,認證使用的Github用戶認證。服務器

示意配置

服務器A(server1)的Nginx配置文件微信

server {
    listen 80;
    listen [::]:80;

    server_name  server1.example.com;

    location = /auth {
        internal;
        proxy_pass http://login.example.com;

        proxy_pass_request_body     off;

        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 401 = @error401;
    location @error401 {
        return 302 http://login.example.com;
    }
    location / {
        try_files $uri $uri/ @proxy;
    }

    # The path has secret content
    location /installs {
        auth_request /auth;
        try_files $uri $uri/ @proxy;
    }

    location @proxy {
        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-Proto https;
        proxy_set_header  X-Forwarded-For $remote_addr;
        proxy_set_header  X-Forwarded-Host $remote_addr;
        proxy_pass    http://127.0.0.1:3003;
    }
}

服務器B(login)的Nginx配置cookie

server {
    listen 80;
    listen [::]:80;

    server_name  login.example.com;

    location / {
    proxy_set_header  Host $host;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-Proto https;
    proxy_set_header  X-Forwarded-For $remote_addr;
    proxy_set_header  X-Forwarded-Host $remote_addr;
    proxy_pass    http://127.0.0.1:4001/;

    }
}

基本流程

  • 用戶訪問服務器A的敏感資源(即路徑/installs中的內容),Nginx經過配置文件中的auth_request字段去請求http://login.example.com/auth,因爲用戶並未在服務器B進行登陸,所以服務器B返回了401無權限的錯誤。session

  • 根據服務器A的配置,發現401錯誤後,會向用戶返回302狀態指向爲服務器B的主機地址(login.example.com)。

  • 用戶瀏覽器跳轉到服務器B,並選擇第三方的用戶認證進行受權(此處以Github爲例),當用戶經過Github進行受權後,迴向服務器B返回用戶的我的信息。

  • 服務器B從第三方反饋回的信息中,檢索出用戶的用戶名(username),而後服務器B會將此用戶名與已有的管理員信息進行對比(此處經過配置文件實現),若是登陸用戶爲合法的管理員帳號,則服務器B受權其登陸進入。若是爲非法用戶,則不對其受權,所以非法用戶沒法得到有效登陸憑證。

    • 若是用戶爲合法用戶:
      那麼服務器B將會生成session,並經過Set-cookie命令告知用戶瀏覽器。用戶經過此Cookie便可得到服務器B的承認受權。當用戶經過此Cookie訪問服務器B中的/auth目錄時,會返回200的狀態碼。

    • 若是用戶爲非法用戶:
      那麼服務器B將不會session,因爲用戶沒法得到承認的Cookie,那麼當用戶再次訪問/auth的路徑時,服務器會返回401錯誤。

  • 假設用戶已經受權成功,那麼當用戶訪問服務器A中的敏感內容/installs時,服務器A訪問服務器B的/auth路徑,此時返回200狀態碼,服務器A則容許用戶進行訪問。

以上,經過auth_request模塊以及相關配置就實現了對敏感內容的訪問限制。並且經過第三方的機制,也無需本身手工實現登陸功能。同時,此方案能夠對同一域名下的不一樣子域名中的內容進行訪問限制。能夠重複利用一個登陸系統,服務於多個其餘系統。

注意事項

  • 設置Express的session時,因爲本案例中使用了不一樣的子域名(server1.example.com及login.example.com),須要特別設置cookiedomain項,以下所示:

    app.use(session({ 
     secret: config.session.secret,
     cookie: {
       path: config.cookie.path,
       domain: config.cookie.domain,
       maxAge: config.cookie.maxAge
     }
    }));

    其中的domain格式爲:.example.com

  • 關於爲什麼使用Github的問題。

    1. 國內能夠訪問(此項排除了Facebook,Google,Twitter等);

    2. 建立應用簡單無需審覈(此項排除了微信,微博等)。

相關文章
相關標籤/搜索