在Function Compute為HTTP觸發器配置JWT認證鑒權,可以確保只有持有有效JWT的用戶端才能訪問,從而提升HTTP服務的安全性,有效防止未經授權的訪問和阻擋惡意攻擊。
背景資訊
簡介
Function Compute支援為HTTP觸發器開啟JWT認證鑒權。JWT(JSON Web Token,RFC7519)是一種基於令牌的便捷請求認證鑒權方案。使用者狀態資訊儲存在Token中,由用戶端提供,函數(服務端)無需儲存,是一種Serverless友好的鑒權方式。Function Compute可以通過使用者綁定在HTTP觸發器上的Public JWKS實現對HTTP調用請求的JWT認證。並根據HTTP觸發器上的配置,將claims
作為參數轉寄給函數,函數無需對請求進行鑒權,只需關注商務邏輯即可。如果需要瞭解JWT的Token
認證流程及基礎知識,請參見基於JWT的token認證和JWT簡介。
JWT認證流程
上圖是Function ComputeHTTP觸發器利用JWT實現認證的整個商務程序時序圖(使用非對稱式加密演算法),步驟詳細解析如下。
用戶端向自訂授權服務發起認證請求,請求中一般會攜帶終端使用者的使用者名稱和密碼。
自訂授權服務讀取請求中的驗證資訊(例如使用者名稱、密碼等)進行驗證,驗證通過之後使用私密金鑰產生標準的
Token
。自訂授權服務將攜帶
Token
的應答返回給用戶端,用戶端需要將這個Token
緩衝到本地。用戶端向HTTP觸發器發送業務請求,請求中攜帶
Token
。HTTP觸發器使用使用者佈建的公開金鑰對請求中的
Token
進行驗證。驗證通過之後,將請求透傳給受保護的函數。
受保護的函數處理業務請求,並進行應答。
HTTP觸發器將業務應答返回給用戶端。
前提條件
使用限制
可以使用任何方式來產生和分發JWT,Function Compute負責通過觸發器配置的Public JWKS來認證JWT。
支援不含
kid
的JWK。支援從
header
、Query
參數(GET)、表單參數(POST)和cookie
中讀取Token。支援將
claims
作為header
、Query
參數(GET)、表單參數(POST)和cookie
轉寄給函數。Function Compute支援為一個HTTP觸發器配置一組JWT(JWKS),在JWKS中尋找與
Token
中的kid
相同的JWK公開金鑰,並使用這個公開金鑰對Token
進行簽名校正。一個觸發器的JWKS最多隻允許一個JWK的kid
不存在或者為空白字串。目前Function Compute的JWT支援如下演算法。
簽名演算法
alg取值
RSASSA-PKCS1-V1_5
RS256,RS384,RS512
RSASSA-PSS
PS256,PS384,PS512
Elliptic Curve (ECDSA)
ES256,ES384,ES512
HMAC
HS256,HS384,HS512
EdDSA
EdDSA
重要HMAC簽名演算法為對稱式加密,安全性相對較低,建議使用安全性更高的非對稱式加密演算法。
使用非對稱式加密演算法時,出於安全考慮,您的JWT中只需要包含公開金鑰資訊即可,不建議包含私密金鑰資訊。
建議使用HTTPS來對請求中的
Token
等敏感資訊進行保護,可以有效避免Token泄漏。
操作步驟
步驟一:配置JWT認證
- 登入Function Compute控制台,在左側導覽列,單擊服務及函數。
- 在頂部功能表列,選擇地區,然後在服務列表頁面,單擊目標服務。
- 在函數管理頁面,單擊目標函數名稱,然後在函數詳情頁面,單擊觸發器管理(URL)頁簽。
在觸發器管理(URL)頁簽,單擊HTTP觸發器操作列的編輯按鈕。
在編輯觸發程序面板,設定以下配置項,然後單擊確定。
認證方式選擇為JWT 認證。
配置JWKS。
為HTTP觸發器配置JWT鑒權,首先需要提供一個有效JWKS(JSON Web Key Set)。您可以自行產生JWKS,或者搜尋JSON Web Key Generator尋找線上可用的產生工具,例如mkjwk.org。如果您已經有pem格式的密鑰,可以藉助工具(例如jwx),將其轉換為JWKS格式。
本文使用mkjwk.org工具產生JWKS,在產生介面選擇Show X.509為Yes才能查看Private Key。在您的代碼中需要使用Private Key簽發JWT Token,請妥善儲存。您可以複製Public Key中的內容填入到控制台中的JWKS的keys數組中。具體可參考下圖。
本文配置的JWKS樣本如下。
{ "keys": [ { "alg": "RS256", "e": "AQAB", "kty": "RSA", "n": "u1LWgoomekdOMfB1lEe96OHehd4XRNCbZRm96RqwOYTTc28Sc_U5wKV2umDzolfoI682ct2BNnRRahYgZPhbOCzHYM6i8sRXjz9Ghx3QHw9zrYACtArwQxrTFiejbfzDPGdPrMQg7T8wjtLtkSyDmCzeXpbIdwmxuLyt_ahLfHelr94kEksMDa42V4Fi5bMW4cCLjlEKzBEHGmFdT8UbLPCvpgsM84JK63e5ifdeI9NdadbC8ZMiR--dFCujT7AgRRyMzxgdn2l-nZJ2ZaYzbLUtAW5_U2kfRVkDNa8d1g__2V5zjU6nfLJ1S2MoXMgRgDPeHpEehZVu2kNaSFvDUQ", "use": "sig" } ] }
在JWT Token 配置配置項中,選擇
Token
所在位置和Token
的名稱。Token
位置支援Header、Cookie、Query參數(GET)和表單參數(POST)。如果Token
位置選擇為Header,則還需為其指定參數名稱和去除首碼。Function Compute在擷取Token時,會刪除去除首碼中設定的首碼內容。重要設定去除首碼時,請注意首碼後面是否存在空格。推薦在首碼欄位後加一個空格,例如
Bearer
。在JWT Claim 轉換配置項中,選擇透傳給函數的參數所在位置、參數原始名稱和參數透傳給函數之後的名稱。
映射參數位置支援Header、Cookie、Query參數(GET)和表單參數(POST)。
佈建要求匹配模式。
匹配全部:所有HTTP請求都需要進行JWT校正。
白名單模式:請求路徑白名單中設定的Path的HTTP請求不需要JWT校正,其他請求需要JWT校正。
黑名單模式:請求路徑黑名單中設定的Path的HTTP請求需要JWT校正,其他請求不需要JWT校正。
白名單模式和黑名單模式支援以下兩種匹配模式。
精確匹配
請求的路徑和設定的路徑完全一致才可以匹配。例如,設定請求路徑黑名單為/a,則來自路徑/a的請求需要JWT校正,來自路徑/a/的請求無需校正。
模糊比對
支援使用萬用字元(*)設定路徑,且萬用字元(*)只能放到路徑的最後。例如,設定請求路徑黑名單為/login/*,則來自路徑首碼為/login/(例如/login/a、/login/b/c/d)的請求均需要JWT校正。
步驟二:操作驗證
在調測工具(本文以Postman工具為例)中,根據HTTP觸發器的JWT配置,填寫訪問地址、Token等,驗證是否可以正常訪問HTTP服務。
使用步驟一中產生的X.509 PEM格式的Private Key作為私密金鑰來頒發JWT Token。以下步驟以Python為例示範通過本地指令碼產生Token的過程。
安裝 PyJWT模組。
pip install PyJWT
在本地運行如下Python樣本指令碼產生JWT Token。
import jwt import time private_key = """ -----BEGIN PRIVATE KEY----- <使用步驟一產生的 X.509 PEM格式的private key> -----END PRIVATE KEY----- """ headers = { "alg": "RS256", "typ": "JWT" } payload = { "sub": "1234567890", "name": "John Snow", "iat": int(time.time()), # token頒發時間 "exp": int(time.time()) + 60 * 60, # 設定token有效時間為1小時 } encoded = jwt.encode(payload=payload, key=private_key.encode(), headers=headers) print("Generated token: %s" % encoded)
使用Postman工具驗證HTTP服務是否可正常訪問。
在目標函數的觸發器管理(URL)頁簽擷取HTTP觸發器的公網訪問地址,將地址填入Postman的URL位置。
在Postman的Headers配置Token參數資訊,然後單擊Send發送請求。本文填寫的Token樣本如下。
名稱
樣本值
說明
Key
Authentication
在JWT Token 配置中設定的參數名稱。
Value
Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9uIFNub3ciLCJhZG1pbiI6dHJ1ZSwiZXhwIjo0ODI5NTk3NjQxfQ.eRcobbpjAd3OSMxcWbmbicOTLjO2vuLR9F2QZMK4rz1JqfSRHgwQVqNxcfOIO9ckDMNlF_3jtdfCfvXfka-phJZpHmnaQJxmnOA8zA3R4wF4GUQdz5zkt74cK9jLAXpokwrviz2ROehwxTCwa0naRd_N9eFhvTRnP3u7L0xn3ll4iOf8Q4jS0mVLpjyTa5WiBkN5xi9hkFxd__p98Pah_Yf0hVQ2ldGSyTtAMmdM1Bvzad-kdZ_wW0jcctIla9bLnOo-Enr14EsGvziMh_QTZ3HQtJuToSKZ11xkNgaz7an5de6PuF5ISXQzxigpFVIkG765aEDVtEnFkMO0xyPGLg
在JWT Token 配置中設定的去除首碼資訊拼接JWT Token。樣本值假設去除首碼已設定為
Bearer
。重要請注意,請求header中JWT參數的首碼和空格需要與JWT Token 配置中設定的去除首碼內容一致,否則會導致觸發器解析Token時出錯並返回invalid or expired jwt錯誤。
配合自訂網域名使用JWT鑒權
如上圖所示,自訂網域名位於HTTP觸發器之前,使用者的請求會先經過自訂網域名的處理,然後才會被HTTP觸發器處理,JWT認證鑒權是位於HTTP觸發器上的邏輯。下文介紹自訂網域名如何使用JWT認證鑒權。
普通自訂網域名
如果為自訂網域名配置了路由,未配置重寫策略,那麼到達HTTP請求中的Path就是自訂網域名請求的Path。
假設自訂網域名www.fc-jwt.com
設定的路由規則如下,且函數jwt-demo
的HTTP觸發器設定的JWT鑒權配置中請求路徑黑名單配置為/fc-jwt/auth/*。
路徑 | 服務名 | 函數名 | 版本 |
/fc-jwt/* | jwt | jwt-demo | 1 |
如果使用者請求URL為/fc-jwt/auth/aliyun,則HTTP觸發器會對請求進行校正,因為到達HTTP觸發器的請求的Path與設定的請求路徑黑名單匹配。
結合自訂網域名的重寫功能
如果為自訂網域名配置了路由,且配置了重寫策略,那麼到達HTTP請求中的Path為自訂網域名重寫後的Path。關於自訂網域名的重寫功能,請參見配置重寫策略(公測中)。
假設自訂網域名www.fc-jwt.com
設定的路由規則如下,函數jwt-demo
的HTTP觸發器設定的JWT鑒權配置中請求路徑黑名單配置為/fc-jwt/auth/*,且配置了萬用字元重寫策略(匹配規則為/fc-jwt/*
,替換規則為 /$1
)。
路徑 | 服務名 | 函數名 | 版本 |
/fc-jwt/* | jwt | jwt-demo | 1 |
如果使用者請求URL為/fc-jwt/auth/aliyun,則重寫後的URL為/auth/aliyun。關於萬用字元重寫規則,請參見萬用字元重寫。此時,HTTP觸發器不會對請求進行校正,因為到達HTTP觸發器的請求的Path為/auth/aliyun,與設定的請求路徑黑名單不匹配。
如果將觸發器請求路徑黑名單配置為/auth/*,那麼HTTP觸發器會對URL為/fc-jwt/auth/aliyun的請求進行JWT校正。