Complete a 3 Question Survey and Earn a re:Post Badge
Help improve AWS Support Official channel in re:Post and share your experience - complete a quick three-question survey to earn a re:Post badge!
為什麼我的 API Gateway Proxy 資源 (具有已啟動快取的 Lambda Authorizer) 會傳回 HTTP 403「使用者未獲得存取此資源的授權」錯誤?
具有已啟動快取之 AWS Lambda Authorizer 的 Amazon API Gateway Proxy 資源會傳回下列 HTTP 403 錯誤訊息: 「使用者未獲得存取此資源的授權」。
簡短描述
**注意:**API Gateway 可能會因為各種原因而傳回 403 **「使用者未獲得存取此資源的授權」**錯誤。本文將解說與 API Gateway Proxy 資源 (具有僅啟用快取的 Lambda Authorizer) 相關的 403 錯誤。如需有關對其他 403 錯誤類型進行疑難排解的資訊,請參閱如何對 API Gateway 的 HTTP 403 錯誤進行疑難排解?
Lambda Authorizer 的輸出會將 AWS Identity and Access Management (IAM) 政策傳回 API Gateway。IAM 政策包含採用下列格式的明確 API Gateway API "Resource"元素:
"arn:aws:execute-api:<region>:<account>:<API_id>/<stage>/<http-method>/[<resource-path-name>/[<child-resources-path>]"
在 Lambda Authorizer 上啟用授權快取時,傳回的 IAM 政策會受到快取。然後,受到快取的 IAM 政策會套用至快取指定存留時間 (TTL) 期間內所發出的任何其他 API 請求。
如果 API 有一個具有窮盡路徑變數為 {proxy+} 的 Proxy 資源,則第一個授權將成功。在快取的 TTL 期間內對其他路徑發出的任何其他 API 請求都會失敗,並傳回下列錯誤:
「訊息」: 「使用者未獲得存取此資源的授權」
因為路徑不符合受到快取之 IAM 政策中定義的明確 API Gateway API "Resource" 元素,所以其他請求失敗。
若要解決此問題,您可以修改 Lambda Authorizer 的程式碼,改為在輸出中傳回萬用字元 (*/*) 資源。如需詳細資訊,請參閱 Lambda 動作的資源與條件。
注意: 若要啟動 Authorizer 快取,您的 Authorizer 必須傳回適用於 API Gateway 中所有方法的政策。Lambda Authorizer 函數的程式碼必須在輸出中傳回萬用字元 (*/*) 資源,才能允許所有資源。除非您在相同的資源路徑上提出兩次相同的請求,否則快取政策預期會快取相同的資源路徑。
解決方法
**注意:**請修改本文中的範例 Lambda Authorizer 函數程式碼片段,以符合您的使用案例。
在下列範例設定中,Lambda 函數從方法的 Amazon Resource Name (ARN) ("event.methodArn") 中擷取 API Gateway 的 ID 值。然後,函數透過將方法 ARN 的路徑與 API 的 id 值和萬用字元 (*/*) 結合,以定義萬用字元 "Resource" 變數。
傳回萬用字元 "Resource" 變數的範例權杖型 Lambda Authorizer 函數程式碼
exports.handler = function(event, context, callback) { var token = event.authorizationToken; var tmp = event.methodArn.split(':'); var apiGatewayArnTmp = tmp[5].split('/'); // Create wildcard resource var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*'; switch (token) { case 'allow': callback(null, generatePolicy('user', 'Allow', resource)); break; case 'deny': callback(null, generatePolicy('user', 'Deny', resource)); break; case 'unauthorized': callback("Unauthorized"); // Return a 401 Unauthorized response break; default: callback("Error: Invalid token"); // Return a 500 Invalid token response } }; // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; }
傳回萬用字元 "Resource" 變數的範例請求參數型 Lambda Authorizer 函數程式碼
exports.handler = function(event, context, callback) { // Retrieve request parameters from the Lambda function input: var headers = event.headers; var queryStringParameters = event.queryStringParameters; var pathParameters = event.pathParameters; var stageVariables = event.stageVariables; // Parse the input for the parameter values var tmp = event.methodArn.split(':'); var apiGatewayArnTmp = tmp[5].split('/'); // Create wildcard resource var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*'; console.log("resource: " + resource); // if (apiGatewayArnTmp[3]) { // resource += apiGatewayArnTmp[3]; // } // Perform authorization to return the Allow policy for correct parameters and // the 'Unauthorized' error, otherwise. var authResponse = {}; var condition = {}; condition.IpAddress = {}; if (headers.headerauth1 === "headerValue1" && queryStringParameters.QueryString1 === "queryValue1" && stageVariables.StageVar1 === "stageValue1") { callback(null, generateAllow('me', resource)); } else { callback("Unauthorized"); } } // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { // Required output: console.log("Resource in generatePolicy(): " + resource); var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; // default version policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; // default action statementOne.Effect = effect; statementOne.Resource = resource; console.log("***Resource*** " + resource); policyDocument.Statement[0] = statementOne; console.log("***Generated Policy*** "); console.log(policyDocument); authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; } var generateAllow = function(principalId, resource) { return generatePolicy(principalId, 'Allow', resource); } var generateDeny = function(principalId, resource) { return generatePolicy(principalId, 'Deny', resource); }
如需如何編輯 Lambda 函數程式碼的詳細資訊,請參閱部署定義為 .zip 檔案存檔的 Lambda 函數。
相關資訊

相關內容
- 已提問 5 個月前lg...
- 已提問 8 個月前lg...
- 已提問 1 年前lg...
- 已提問 3 年前lg...