【问题标题】:How to create an authentication middleware inside an AWS Lambda如何在 AWS Lambda 中创建身份验证中间件
【发布时间】:2019-04-03 00:06:48
【问题描述】:

我正在使用 AWS Cognito 对我的用户进行身份验证,一旦通过身份验证,他们就可以调用我的 API(API 网关 + Lambda)。我正在使用无服务器框架完成所有这些工作。

一旦通过身份验证,当他们调用需要此身份验证的端点时,我的 lambda 将通过request.RequestContext.Authorizer["claims"] 接收用户属性。我有创建一个身份验证中间件以将当前用户注入上下文的想法。但我确定我做错了什么(或者可以改进)。

它是如何工作的:

my-lambda.go:

package main

import (
    "context"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/company/api/middlewares"
)

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    fmt.Println(ctx.user)

    return events.APIGatewayProxyResponse{}, nil
}

func main() {
    lambda.Start(
        middlewares.Authentication(Handler),
    )
}

middlewares/authentication.go

package middlewares

import (
    "context"

    "github.com/aws/aws-lambda-go/events"
    "github.com/company/api/models"
)

func Authentication(next func(context.Context, events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)) func(context.Context, events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    var user models.User

    return func(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        claims := request.RequestContext.Authorizer["claims"]

        // Find user by claims properties.
        if err := user.Current(claims); err != nil {
            return events.APIGatewayProxyResponse{}, err
        }

        ctx.user = user
        return next(ctx, request)
    }
}

模型/user.go:

package models

import (
    "github.com/jinzhu/gorm"
    "github.com/mitchellh/mapstructure"
)

type User struct {
    gorm.Model
    // Override ID cause we are using cognito.
    Email string `gorm:"primary_key,not null"`
    Site  Site
}

func (u *User) Current(claims interface{}) error {
    if err := mapstructure.Decode(claims, u); err != nil {
        panic(err)
    }

    if err := Database.Find(u).Error; err != nil {
        return err
    }
    return nil
}

我有两个问题:

  • 这是定义接收一个函数并返回另一个函数的函数(身份验证函数)的正确方法吗?因为它太冗长了,我觉得这是错误的。
  • 有没有办法用user 属性扩充ctx?我正在尝试的方式,我看到错误ctx.user undefined (type context.Context has no field or method user)

【问题讨论】:

    标签: amazon-web-services go aws-lambda amazon-cognito


    【解决方案1】:

    关于使用中间件的第一个问题:

    这种方法当然没有错。如果定义函数类型并使用定义的名称,可能函数看起来会好一些。 net/httpHandlerFunc 做同样的事情:

    type HandlerFunc func(ResponseWriter, *Request)
    

    这将使中间件的签名更合理:

    func AuthMiddleware(nextHop HandlerFunc) HandlerFunc
    

    编辑:lambda 库没有为函数签名定义这样的类型吗?我希望存在一个。

    我也不知道后缀 Middleware 在你的情况下是否有意义,但我认为 some suffix 应该让你为函数名称提供更多上下文并使其更易于理解。 AuthenticationMiddleware 就是一个例子。

    编辑:刚刚看到包名。真的是 LGTM。

    第二个问题:

    请参阅this,了解context 的正确用法。还有一个常见的陷阱:context.WithValue 返回要使用的新上下文。因此,您不应期望传递的参数上下文会发生变化,而应使用返回的新参数。

    【讨论】:

      猜你喜欢
      • 2016-12-22
      • 1970-01-01
      • 2020-11-11
      • 2020-11-04
      • 1970-01-01
      • 2017-02-17
      • 2018-10-21
      • 2022-01-16
      • 2019-11-18
      相关资源
      最近更新 更多