[ Nginx ] 微服務權限管理
最近被問到,微服務系統要怎麼管理權限。上網查了一下,發現這方面的文章好像不多,加上好久沒更新了,想說就來分享一下。
我傾向權限通通交給 server來管理,這樣不管是用什麼樣的方式來驗證用戶,都不影響其他微服務運作。
因為要依賴到 Nginx,所以就直接使用 Docker了,先建立一個 docker-conpose.yaml文件。
接著建立一個資料夾,並在裡面建立一個文件 default.conf。
不打算使用 Docker的朋友可以直接安裝 nginx(怎麼安裝網上應該很好查),然後直接修改 /etc/nginx/conf.d/default.conf(位置可能會有所差異),但要將"http://web:8000"修改成"http://localhost:8000。
Django建立的流程不是本文重點,所以就直接切入重點。先建立一個資料夾 web,並在裡面建立一個 Django專案(這個 demo將專案命名為 src)。接著在專案中建立資料夾 media,並在裡面建立 __init__.py和 views.py。
首先修改 src/urls.py。
其中 r'media/(?P<filepath>.+)'是獲取所有在/media/後的字串,並放入 filePath的變數中。
urlquote()的用途是當 filePath中有非英文符號時,會對該字串進行轉譯。
接著將路徑放入 header裡的 X-Accel-Redirect。
最後在 Content-Type中放一個空字串。(建立空的 Content-Type目的是讓 Nginx自己判斷 response的 Content-Type的值,若不設定可能會誤以為用戶是要下載等狀況)
到此,訪問 internal的設定就已經完成了。 最後資料夾結構如下。
當中我已經在/nginx/media-root的路徑中放了名為"job_hunt.jpg"的圖片。
接著就直接下指令"docker-conpose up --build",就可以透過一般訪問 media的方式訪問 media中的靜態文件。
不是使用 Docker的朋友就直接啟動 Django並重啟 Nginx即可。
最後直接在瀏覽器上訪問 http://localhost/media/job_hunt.jpg。
另外,不一定要從 url來告訴 server檔案路徑,可以透過任何方式,比如透過 primary key取得檔案路徑等,最終只需要設定 response['X-Accel-Redirect']時給予正確的路徑即可。這樣就不一定要寫麻煩的 regular expression了。
若有什麼不清楚的地方,歡迎參考我的Bitbucket。
觀察了一下,台灣 Django的職缺真的好少,幾年下來都沒什麼變化,跟 Ruby on Rails差好多。(淚
我傾向權限通通交給 server來管理,這樣不管是用什麼樣的方式來驗證用戶,都不影響其他微服務運作。
因為要依賴到 Nginx,所以就直接使用 Docker了,先建立一個 docker-conpose.yaml文件。
version: '3' services: web: build: context: ./web dockerfile: Dockerfile command: gunicorn -b 0.0.0.0:8000 src.wsgi ports: - "8000:8000" volumes: - ./web/src:/web/src - ./volumes/media-root:/web/media-root nginx: image: nginx ports: - "80:80" volumes: - ./volumes/media-root:/nginx/media-root - ./nginx/default.conf:/etc/nginx/conf.d/default.conf這個 yaml檔目的是運行 Nginx,其中主要是將設定檔放入 container中。
接著建立一個資料夾,並在裡面建立一個文件 default.conf。
server { listen 80 default_server; location /protectedMedia { internal; alias /nginx/media-root; } location / { proxy_pass http://web:8000; } }在 server的區塊中建立兩個路徑,"/"和"/protectedMedia","/"將會作為 Django的 proxy,"/protectedMedia"則會專門處理路徑/nginx/media-root中的靜態文件,其中 internal的設定是指這個路徑僅接受內部訪問,所以是沒辦法直接從瀏覽器訪問的。
不打算使用 Docker的朋友可以直接安裝 nginx(怎麼安裝網上應該很好查),然後直接修改 /etc/nginx/conf.d/default.conf(位置可能會有所差異),但要將"http://web:8000"修改成"http://localhost:8000。
Django建立的流程不是本文重點,所以就直接切入重點。先建立一個資料夾 web,並在裡面建立一個 Django專案(這個 demo將專案命名為 src)。接著在專案中建立資料夾 media,並在裡面建立 __init__.py和 views.py。
首先修改 src/urls.py。
# src/urls.py from django.contrib import admin from django.urls import path, re_path from media.views import Media urlpatterns = [ path('admin/', admin.site.urls), re_path(r'media/(?P<filepath>.+)', Media.as_view(), name='media'), ]這裡需要使用到 re_path,允許開發者使用 regular expression來辨識前端請求的 url。
其中 r'media/(?P<filepath>.+)'是獲取所有在/media/後的字串,並放入 filePath的變數中。
# media/views.py from django.views import View from django.http import HttpResponse from django.utils.http import urlquote class Media(View): def get(self, request, filePath): filePath = urlquote(filePath) response = HttpResponse() url = '/protectedMedia/{}'.format(filePath) response['X-Accel-Redirect'] = url response['Content-Type'] = '' return response獲取 filePath後就可以建立訪問 Nginx中的 /protectedMedia的完整路徑。
urlquote()的用途是當 filePath中有非英文符號時,會對該字串進行轉譯。
接著將路徑放入 header裡的 X-Accel-Redirect。
最後在 Content-Type中放一個空字串。(建立空的 Content-Type目的是讓 Nginx自己判斷 response的 Content-Type的值,若不設定可能會誤以為用戶是要下載等狀況)
到此,訪問 internal的設定就已經完成了。 最後資料夾結構如下。
接著就直接下指令"docker-conpose up --build",就可以透過一般訪問 media的方式訪問 media中的靜態文件。
不是使用 Docker的朋友就直接啟動 Django並重啟 Nginx即可。
最後直接在瀏覽器上訪問 http://localhost/media/job_hunt.jpg。
這次文章簡化了很多步驟,主要是分享如何透過 server訪問 Nginx中 internal的連結,因此沒有真的設定權限,會觀看本文的朋友,應該已經有基本的能力在 server端對連結設定權限了。
雖然本例並沒有提供其他的微服務,但可以用同樣的方式,將處理 media的區塊修改成其他微服務的 proxy。另外,不一定要從 url來告訴 server檔案路徑,可以透過任何方式,比如透過 primary key取得檔案路徑等,最終只需要設定 response['X-Accel-Redirect']時給予正確的路徑即可。這樣就不一定要寫麻煩的 regular expression了。
若有什麼不清楚的地方,歡迎參考我的Bitbucket。
觀察了一下,台灣 Django的職缺真的好少,幾年下來都沒什麼變化,跟 Ruby on Rails差好多。(淚
留言
張貼留言