1

我正在尝试找到一种方法来允许在 AWS 的自定义授权方中使用访客模式

基本上,我想要实现的是以下场景:

  • 如果请求中没有Authorization标头,则触发响应一些数据的 lambda 函数
  • 如果有Authorization标头,那么我的自定义授权者应该检查 JWT 令牌和Allowor Denycustom-authorizer如果返回则触发 lambdaAllow

我看到我可以实现其中一个但不能同时实现,即我可以打开可以正常工作的端点(authorizer完全删除),或者我可以authorizer再次正常工作。

custom-authorizer然而,当没有Authorization标题时,我看不到绕过的方法。

无服务器中的示例配置:

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /hello
          method: get
          private: true
          authorizer:
            identitySource: method.request.header.Authorization # Can this be optional?
            name: custom-authorizer
  custom-authorizer:
    handler: authorizer.handler

从我的测试中,我可以确认一旦authorization存在并且Authorization请求中没有标头,那么我custom-authorizer根本不会被触发,API 网关会立即响应401 Unauthorized.

请注意,在我的访客模式下,我不想获得自定义 API 网关响应(这是可能的并且有效)。我想触发 lambda 函数,就像根本没有授权一样。

我得出结论这是不可能的,唯一的解决方法是删除authorization然后在 lambda 中执行一些自定义代码。

有什么建议吗?

4

2 回答 2

1

如果您将sls 事件处理程序配置为httpApi*,而不是http,则identitySource是可选输入authorizer(假设无服务器 api 与 AWS api 匹配)。

相关的 CloudFormationAWS::ApiGatewayV2::Authorizer文档在此处

如您所见,如果identitySource已配置但客户端请求中不存在,Apig 将返回401. 如果您identitySource从配置中省略,所有请求都将发送到您的授权者 lambda。然后,您的 lambda 可以处理三种情况:无令牌、坏令牌、好令牌。

* httpApiApiGatewayV2在 AWS CloudFormation 中一样部署。正如 Serverless 文档所说,V2“比 v1 更快、更便宜”。api 和功能集在“HTTP Api”(V2)“Rest Api”(V1)之间有些不同,但httpApi它是一个不错的默认选择。

于 2021-11-21T16:42:39.493 回答
0

跟进@fedonev的答案是完整的解决方案:

  • 使用HTTP API而不是REST API.
  • 更新custom-authorizer

让我们开始serverless.yml根据更新和不同的HTTP API 语法进行相应的更新:

替换events.httpevents.httpApi并添加httpApi.authorizerprovider. 更新serverless.yml

provider:
  httpApi:                          # Added
    authorizers:
      customAuthorizer:
        type: request
        functionName: custom-authorizer

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:                    # Changed
          path: /hello
          method: get
          authorizer:
            name: customAuthorizer  # Changed

custom-authorizer:
  handler: authorizer.handler

接下来,我们还需要更新我们的授权处理函数。它仍然需要像使用 REST API 一样返回策略。然而......没有event.authorizationToken也没有event.methodArn了(我把它注释掉以供参考):

module.exports.handler = async (event) => {
  if (
    !event.headers.authorization ||
    event.headers.authorization === 'Bearer ABCDEF'
  ) {
    // if (event.authorizationToken === 'Bearer ABCDEF')
    return {
      principalId: 'anonymous',
      policyDocument: {
        Version: '2012-10-17',
        Statement: [
          {
            Action: 'execute-api:Invoke',
            Effect: 'Allow',
            Resource: event.routeArn,
            // Resource: event.methodArn,
          },
        ],
      },
    };
  }
  throw Error('Unauthorized');
};

现在,我们可以看到我们可以完全控制授权,我们可以检查令牌是否存在:(!event.headers.authorization这模拟访客模式)或令牌是否有效:event.headers.authorization === 'Bearer ABCDEF'。如果令牌无效,我们会抛出401 Unauthorized预期的错误。

最后,值得注意的是所有headers密钥都是小写的并且principalId是强制性的(如前所述,当使用 REST API 时,授权者在没有它的情况下工作)。

部署和享受!

于 2021-11-22T10:38:51.387 回答