发布于 2026-01-06 4 阅读
0

使用 Golang 和 AWS Cognito 进行身份验证

使用 Golang 和 AWS Cognito 进行身份验证

什么是Cognito?

应用程序的身份验证在系统中非常重要,但也非常敏感,需要考虑各种实现方式、安全性和验证方法。

我决定写一篇博文,介绍一下Cognito,这是 AWS 提供的一款非常棒的工具,可以帮助您对 Web 和移动应用程序进行用户身份验证和验证,但很多人并不了解它。

Cognito 是一个 AWS 平台,负责创建和验证用户访问数据,以及注册用户和存储其信息,此外还能生成 OAuth 令牌,并且 Cognito 还可以提供所有用户验证。

我们可以创建一些用户数据,例如:电子邮件、姓名、电话号码、出生日期、昵称、性别、网站等等,我们还可以添加自定义字段。

Cognito 仍然允许我们与“联合提供商”(也称为社交登录)一起使用,例如 Google、Facebook 和 GitHub,我们不会在本文中讨论这一点,但使用 Cognito 是可以做到这一点的。

我们该怎么办?

我们将创建一些端点来展示 Cognito 的工作原理,我们将创建用户、确认电子邮件、登录、使用 Cognito 提供的令牌搜索用户、更新信息。

项目设置

我们将做一些非常简单的事情,我们不会去考虑项目负责人,我们只想关注知识的运用。

为了创建端点,我们将使用gin

让我们创建以下文件:

  • 我们应用程序的入口点main.go位于项目根目录。

  • .env保存认知凭证

  • 一个名为cognitoClient 的粘贴文件,位于一个名为cognito.go

  • 有一个名为 的文件request.http,用于完成您的请求。

结构如下:

项目结构

在 AWS 上设置 Cognito

在开始编写代码之前,我们将在 AWS 中配置 Cognito,以便访问面板并通过 Cognito 进行搜索。创建池之后,选择“将用户目录添加到您的应用程序”选项。

对于提供商类型,选择Cognito 用户池选项,您可以选择允许使用电子邮件、用户名和电话号码登录,也可以仅选择电子邮件登录,选择您偏好的方式,然后选择 assim 进入第一阶段:

Cognito配置步骤1

我还需要配置一些东西,走吧!

  • 密码策略模式允许您选择特定的策略,让我们取消Cognito 的默认设置
  • 多因素身份验证允许我们的登录进行双因素身份验证,我们先不使用,但如果需要,您可以实施它,您可以选择不使用 MFA
  • 最后,或者说用户帐户恢复,您可以选择恢复帐户的方式,您可以选择电子邮件。

认知配置步骤2.1

认知配置步骤2.2

下一步:

  • 自助注册,我们将允许任何人进行注册,请留下您的选择。
  • Cognito 辅助验证和确认,允许 Cognito 负责确认用户的身份,进行检查,并选择“发送电子邮件消息,验证电子邮件地址”选项。
  • 验证属性更改,选中此选项后,更新用户电子邮件时需要再次进行验证。
  • 必填属性,选择创建新用户时要设为必填的字段,您将选择选项,电子邮件(和姓名),并且您的父亲的姓名也是必填项。
  • 自定义属性是可选的,但您可以添加自定义字段,例如,您可以创建一个名为“custom_id任意”的字段uuid

这一阶段也发生了:

认知配置步骤2.3

认知配置步骤2.4

认知配置步骤2.5

接下来,选择“使用 Cognito 发送电子邮件”选项,这样我们就无需配置任何内容来触发电子邮件。

下一步,在“用户池名称”中输入您想要的名称,在“应用程序客户端名称”中也输入您想要的名称,然后继续。

最后阶段我们不需要做任何更改,只需完成并创建用户池即可。

在“访问或认知 > 用户池”中,选择您刚刚创建的池,此部分将列出您的应用程序的所有用户,并且可以撤销用户的令牌、停用、验证等功能。

我们将指定池的 ID,以便能够使用Go SDK for AWS 来访问已创建的池。在“应用程序集成” > “应用程序客户端列表”中,您可以看到我们的客户端 ID

Cognito客户端ID

让我们把这个ID保存到.env文件中:

COGNITO_CLIENT_ID=client_id
Enter fullscreen mode Exit fullscreen mode

请记住,您仍然需要 AWS 凭证,通常位于/Users/your-user/.aws目录中。如果您尚未配置,请参阅此处了解如何配置。

实施 Cognito

让我们把 Cognito 部分单独放到一个文件中。

用户注册

在文件中cognito.go,我们将初始化 Cognito 并创建界面:

  package congnitoClient

  import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    cognito "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
    "github.com/google/uuid"
  )

  type User struct {
    Name     string `json:"name" binding:"required"`
    Email    string `json:"email" binding:"required,email"`
    Password string `json:"password" binding:"required"`
  }

  type CognitoInterface interface {
    SignUp(user *User) error
  }

  type cognitoClient struct {
    cognitoClient *cognito.CognitoIdentityProvider
    appClientID   string
  }

  func NewCognitoClient(appClientId string) CognitoInterface {
    config := &aws.Config{Region: aws.String("us-east-1")}
    sess, err := session.NewSession(config)
    if err != nil {
      panic(err)
    }
    client := cognito.New(sess)

    return &cognitoClient{
      cognitoClient: client,
      appClientID:   appClientId,
    }
  }

  func (c *cognitoClient) SignUp(user *User) error {
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

首先,我们创建一个名为 的结构体User,该结构体将包含我们需要保存到 Cognito 中的用户字段。

然后我们创建一个interface名为 `<T>` 的类CognitoInterface,其中将包含我们将要使用的方法,首先我们只有一个 `<T>`,SignUp它将接收一个User指向结构体的指针。

然后我们将创建另一个结构体,cognitoClient其中包含我们的实例,NewCognitoClient该实例将是我们的构造函数。

如前所述,NewCognitoClient它将类似于我们的构造函数,我们将在其中创建与 AWS 的会话并返回此连接。此连接可以是全局变量,但在我们的示例中我们不会这样做,您需要根据自己的用例来判断哪种方法最佳。

现在让我们来实现SignUp

  func (c *cognitoClient) SignUp(user *User) error {
    userCognito := &cognito.SignUpInput{
      ClientId: aws.String(c.appClientID),
      Username: aws.String(user.Email),
      Password: aws.String(user.Password),
      UserAttributes: []*cognito.AttributeType{
        {
          Name:  aws.String("name"),
          Value: aws.String(user.Name),
        },
        {
          Name:  aws.String("email"),
          Value: aws.String(user.Email),
        },
        {
          Name:  aws.String("custom:custom_id"),
          Value: aws.String(uuid.NewString()),
        },
      },
    }
    _, err := c.cognitoClient.SignUp(userCognito)
    if err != nil {
      return err
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

我们将使用Cognito 来组装要发送到AWS SDK 的AttributeType参数,请注意,我们的自定义字段需要放在前面,否则将不会被接受,我们刚刚使用 Google 包创建了一个 uuid,此字段只是为了演示如何使用自定义属性。SignUpcustom_idcustom

ClientId字段指的是COGNITO_CLIENT_ID我们的环境,我们将在启动时传递它main.go

这就是我们拯救用户所需要的,很简单,对吧?

别忘了以以下内容开始项目:

  go mod init <your project name>
Enter fullscreen mode Exit fullscreen mode

并安装必要的软件包:

  go mod tidy
Enter fullscreen mode Exit fullscreen mode

确认账户

我们来创建另一个函数,用于通过电子邮件验证用户帐户。要验证帐户,用户需要输入通过电子邮件发送的验证码。让我们创建一个新的结构体,并将新ConfirmAccount方法添加到接口中:

  type UserConfirmation struct {
    Email string `json:"email" binding:"required,email"`
    Code  string `json:"code" binding:"required"`
  }
Enter fullscreen mode Exit fullscreen mode
  type CognitoInterface interface {
    SignUp(user *User) error
    ConfirmAccount(user *UserConfirmation) error
  }
Enter fullscreen mode Exit fullscreen mode

现在让我们来实现:

  func (c *cognitoClient) ConfirmAccount(user *UserConfirmation) error {
    confirmationInput := &cognito.ConfirmSignUpInput{
      Username:         aws.String(user.Email),
      ConfirmationCode: aws.String(user.Code),
      ClientId:         aws.String(c.appClientID),
    }
    _, err := c.cognitoClient.ConfirmSignUp(confirmationInput)
    if err != nil {
      return err
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

很简单,我们将使用ConfirmSignUpInputcognito 包中的方法来组装参数,记住,其中Username是用户的电子邮件地址。最后,我们将调用ConfirmSignUp该方法并传递参数confirmationInput

请记住,我们只返回了错误信息,您可以改进并检查错误消息的类型。

登录

这应该是使用频率最高的功能,我们来创建一个名为 `method` 的方法SignIn和一个结构体:

  type UserLogin struct {
    Email    string `json:"email" binding:"required,email"`
    Password string `json:"password" binding:"required"`
  }
Enter fullscreen mode Exit fullscreen mode
  type CognitoInterface interface {
    SignUp(user *User) error
    ConfirmAccount(user *UserConfirmation) error
    SignIn(user *UserLogin) (string, error)
  }
Enter fullscreen mode Exit fullscreen mode

我们SignIn将收到一个UserLogin

让我们来实现:

  func (c *cognitoClient) SignIn(user *UserLogin) (string, error) {
    authInput := &cognito.InitiateAuthInput{
      AuthFlow: aws.String("USER_PASSWORD_AUTH"),
      AuthParameters: aws.StringMap(map[string]string{
        "USERNAME": user.Email,
        "PASSWORD": user.Password,
      }),
      ClientId: aws.String(c.appClientID),
    }
    result, err := c.cognitoClient.InitiateAuth(authInput)
    if err != nil {
      return "", err
    }
    return *result.AuthenticationResult.AccessToken, nil
  }
Enter fullscreen mode Exit fullscreen mode

我们将使用InitiateAuthaws cognito 包中的函数,我们需要传递username(用户的电子邮件),password以及AuthFlow,此字段指的是我们将允许的访问类型,在我们的例子中是USER_PASSWORD_AUTH

如果您收到类似这样的错误信息:

You trusted all proxies, this is NOT safe. We recommend you to set a value

需要启用该ALLOW_USER_PASSWORD_AUTH流程,要进行配置,请访问 AWS 控制面板上的 Cognito,然后转到:

用户池>选择您的池>应用集成>应用客户端列表>选择客户端,将打开此屏幕:

认知流程 1

点击编辑,在身份验证流程中选择ALLOW_USER_PASSWORD_AUTH选项,然后保存,这样您就可以使用用户的密码和电子邮件登录了。

列出用户

Paramostrar como utilizar o token jwt fornecido pelo cognito vamos criar um end quemostra os bados do usuário salvos no cognito apenas com o token.

让我们创建另一个函数,GetUserByToken该函数将接收一个令牌并返回一个结构体,GetUserOutput该结构体的类型将从 cognito 包中获取。

  type CognitoInterface interface {
    SignUp(user *User) error
    ConfirmAccount(user *UserConfirmation) error
    SignIn(user *UserLogin) (string, error)
    GetUserByToken(token string) (*cognito.GetUserOutput, error)
  }
Enter fullscreen mode Exit fullscreen mode

点击后GetUserOutput即可查看该结构体内部的内容。

  type GetUserOutput struct {
    _ struct{} `type:"structure"`
    MFAOptions []*MFAOptionType `type:"list"`
    PreferredMfaSetting *string `type:"string"`
    UserAttributes []*AttributeType `type:"list" required:"true"`
    UserMFASettingList []*string `type:"list"`
    Username *string `min:"1" type:"string" required:"true" sensitive:"true"`
  }
Enter fullscreen mode Exit fullscreen mode

其中_ struct{}包含我们为用户创建的自定义属性,在本例中为custom_id

让我们来实现:

  func (c *cognitoClient) GetUserByToken(token string) (*cognito.GetUserOutput, error) {
    input := &cognito.GetUserInput{
      AccessToken: aws.String(token),
    }
    result, err := c.cognitoClient.GetUser(input)
    if err != nil {
      return nil, err
    }
    return result, nil
  }
Enter fullscreen mode Exit fullscreen mode

我们使用GetUsercognito 包,它只需要一个AccessTokencognito 本身提供的标记。

更新密码

最后,我们将更新用户的密码。为此,我们需要用户的电子邮件地址和新密码。我们已经有了UserLogin包含所需字段的结构体,我们将重复使用它。如果您愿意,也可以专门为此函数创建一个新的结构体。让我们创建该UpdatePassword函数:

  type CognitoInterface interface {
    SignUp(user *User) error
    ConfirmAccount(user *UserConfirmation) error
    SignIn(user *UserLogin) (string, error)
    GetUserByToken(token string) (*cognito.GetUserOutput, error)
    UpdatePassword(user *UserLogin) error
  }
Enter fullscreen mode Exit fullscreen mode

让我们来实现:

  func (c *cognitoClient) UpdatePassword(user *UserLogin) error {
    input := &cognito.AdminSetUserPasswordInput{
      UserPoolId: aws.String(os.Getenv("COGNITO_USER_POOL_ID")),
      Username:   aws.String(user.Email),
      Password:   aws.String(user.Password),
      Permanent:  aws.Bool(true),
    }
    _, err := c.cognitoClient.AdminSetUserPassword(input)
    if err != nil {
      return err
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

我们将使用AdminSetUserPasswordcognito 包中的函数,需要传入用户的电子邮件地址和新密码,此外还需要传入一个文件UserPoolId,该文件将放在COGNITO_USER_POOL_ID一个文件中。.env要在 AWS 中查找该文件,只需访问您的存储池并复制该文件即可。User pool ID

池 ID

我们还会传递一个信息Permanent,告知用户这是一个永久密码;您也可以传递一个信息false,这样 Cognito 就会为用户创建一个临时密码,这取决于您在应用程序中使用的策略。

创建主界面

让我们创建我们的 .cognito.xmlmain.go文件,我们将在这个文件中启动 Cognito 并创建我们的路由。

  func main() {
    err := godotenv.Load()
    if err != nil {
      panic(err)
    }
    cognitoClient := congnitoClient.NewCognitoClient(os.Getenv("COGNITO_CLIENT_ID"))
    r := gin.Default()

    fmt.Println("Server is running on port 8080")
    err = r.Run(":8080")
    if err != nil {
      panic(err)
    }
  }
Enter fullscreen mode Exit fullscreen mode

首先,我们将使用godotenv包加载我们的环境,然后启动 cognito 客户端,传递COGNITO_CLIENT_ID我们之前获取的参数,然后启动 gin 并创建一个服务器,这就足够了。

创建端点

创建用户

让我们在main.go文件内部创建一个函数,我们把它命名为CreateUser

  func CreateUser(c *gin.Context, cognito congnitoClient.CognitoInterface) error {
    var user congnitoClient.User
    if err := c.ShouldBindJSON(&user); err != nil {
      return errors.New("invalid json")
    }
    err := cognito.SignUp(&user)
    if err != nil {
      return errors.New("could not create use")
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

很简单,我们只需使用 gin 的函数将接收到的内容转换为我们的结构体ShouldBindJSON,然后调用SignUp我们在 中创建的cognito.go

现在让我们在函数内部创建端点main.go

  r.POST("user", func(context *gin.Context) {
        err := CreateUser(context, cognitoClient)
        if err != nil {
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        context.JSON(http.StatusCreated, gin.H{"message": "user created"})
    })
Enter fullscreen mode Exit fullscreen mode

我们调用刚刚创建的函数CreateUser,如果出现错误,则抛出异常StatusBadRequest,如果成功,则返回一个值StatusCreated,让我们进行测试。

让我们先go mod tidy下载所有软件包,然后运行应用程序。go run main.go

现在我们可以在request.http文件中创建一个调用并执行:

POST http://localhost:8080/user HTTP/1.1
content-type: application/json

{
  "Name": "John Doe",
  "email": "wivobi1159@bitofee.com",
  "password": "Pass@1234"
}
Enter fullscreen mode Exit fullscreen mode

如果一切正常,我们将收到以下信息:

{
  "message": "user created"
}
Enter fullscreen mode Exit fullscreen mode

现在进入 AWS 上的 Cognito 控制面板,访问池,然后访问用户,我们就能找到我们的用户了:

用户

确认用户

请注意,我们上面创建的用户尚未经过验证,让我们来验证一下!

ConfirmAccount在文件中创建一个名为以下函数的函数main.go

  func ConfirmAccount(c *gin.Context, cognito congnitoClient.CognitoInterface) error {
    var user congnitoClient.UserConfirmation
    if err := c.ShouldBindJSON(&user); err != nil {
      return errors.New("invalid json")
    }
    err := cognito.ConfirmAccount(&user)
    if err != nil {
      return errors.New("could not confirm user")
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

和之前一样,让我们​​把主体转换成UserConfirmation结构体,然后传递给ConfirmAccountin cognito.go

让我们创建端点:

  r.POST("user/confirmation", func(context *gin.Context) {
        err := ConfirmAccount(context, cognitoClient)
        if err != nil {
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        context.JSON(http.StatusCreated, gin.H{"message": "user confirmed"})
    })
Enter fullscreen mode Exit fullscreen mode

也很简单,我们只需处理错误并返回一条消息,让我们创建调用并进行测试:

POST http://localhost:8080/user/confirmation HTTP/1.1
content-type: application/json

{
  "email": "wivobi1159@bitofee.com",
  "code": "363284"
}
Enter fullscreen mode Exit fullscreen mode

我们将收到以下信息:

{
  "message": "user confirmed"
}
Enter fullscreen mode Exit fullscreen mode

现在再次通过 AWS 控制面板访问 Cognito,请注意用户已确认。请记住,您需要输入有效的电子邮件地址。您可以使用临时电子邮件地址进行测试,但该电子邮件地址必须有效,因为 Cognito 会发送确认码,并且该确认码必须有效才能成功确认。

用户已确认

登录

现在让我们创建令牌,为此,请在main.go文件中创建一个名为 `token` 的函数SignIn,该函数将返回一个错误和一个令牌。

  func SignIn(c *gin.Context, cognito congnitoClient.CognitoInterface) (string, error) {
    var user congnitoClient.UserLogin
    if err := c.ShouldBindJSON(&user); err != nil {
      return "", errors.New("invalid json")
    }
    token, err := cognito.SignIn(&user)
    if err != nil {
      return "", errors.New("could not sign in")
    }
    return token, nil
  }
Enter fullscreen mode Exit fullscreen mode

与其他函数一样,我们将主体转换为UserLogin结构体并将其传递给SignInof cognito.go

让我们创建端点:

  r.POST("user/login", func(context *gin.Context) {
        token, err := SignIn(context, cognitoClient)
        if err != nil {
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        context.JSON(http.StatusCreated, gin.H{"token": token})
    })
Enter fullscreen mode Exit fullscreen mode

现在我们token向用户返回一个结果,让我们创建调用并进行测试:

POST http://localhost:8080/user/login HTTP/1.1
content-type: application/json

{
  "email": "wivobi1159@bitofee.com",
  "password": "Pass@1234"
}
Enter fullscreen mode Exit fullscreen mode

发起调用时,我们将收到我们的 JWT 令牌:

{
  "token": "token_here"
}
Enter fullscreen mode Exit fullscreen mode

用户 JWT 令牌

如果我们获得了 jwt 令牌,我们可以使用网站jwt.io查看其中的内容。

列出用户

现在我们将仅使用令牌列出 Cognito 中保存的用户数据,为此,我们将创建一个名为GetUserByToken`in` 的函数main.go,并且我们需要一个结构体来表示我们将返回给用户的响应,我们main也将在 `in` 中创建它:

  type UserResponse struct {
    ID            string `json:"id"`
    Name          string `json:"name"`
    Email         string `json:"email"`
    CustomID      string `json:"custom_id"`
    EmailVerified bool   `json:"email_verified"`
  }

  func main() {}
Enter fullscreen mode Exit fullscreen mode

现在是函数:

  func GetUserByToken(c *gin.Context, cognito congnitoClient.CognitoInterface) (*UserResponse, error) {
    token := strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
    if token == "" {
      return nil, errors.New("token not found")
    }
    cognitoUser, err := cognito.GetUserByToken(token)
    if err != nil {
      return nil, errors.New("could not get user")
    }
    user := &UserResponse{}
    for _, attribute := range cognitoUser.UserAttributes {
      switch *attribute.Name {
      case "sub":
        user.ID = *attribute.Value
      case "name":
        user.Name = *attribute.Value
      case "email":
        user.Email = *attribute.Value
      case "custom:custom_id":
        user.CustomID = *attribute.Value
      case "email_verified":
        emailVerified, err := strconv.ParseBool(*attribute.Value)
        if err == nil {
          user.EmailVerified = emailVerified
        }
      }
    }
    return user, nil
  }
Enter fullscreen mode Exit fullscreen mode

这将是最大的功能,我们需要将从 Cognito 接收到的数据映射到我们的UserResponse结构体中,我们使用 `a`for和 `a`来实现这一点switch,当然我们可以改进它,但为了示例起见,我们先保持这样。此外,要映射自定义属性,我们需要custom在前面加上 `a`,例如 ` custom:custom_ida`。

我们还会检查用户是否在请求头中传递了令牌,如果没有,则返回错误。

让我们创建端点:

  r.GET("user", func(context *gin.Context) {
        user, err := GetUserByToken(context, cognitoClient)
        if err != nil {
            if err.Error() == "token not found" {
                context.JSON(http.StatusUnauthorized, gin.H{"error": "token not found"})
                return
            }
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        context.JSON(http.StatusOK, gin.H{"user": user})
    })
Enter fullscreen mode Exit fullscreen mode

我们执行与其他端点相同的验证,但现在我们检查错误类型,如果是该token not found类型,则返回一个StatusUnauthorized

我们来测试一下:

GET http://localhost:8080/user HTTP/1.1
content-type: application/json
Authorization: Bearer token_jwt
Enter fullscreen mode Exit fullscreen mode

让我们接收用户:

{
  "user": {
    "id": "50601dc9-7234-419a-8427-2a4bda92d33f",
    "name": "John Doe",
    "email": "wivobi1159@bitofee.com",
    "custom_id": "cb748d09-40de-457a-af23-ed9483d69f8d",
    "email_verified": true
  }
}
Enter fullscreen mode Exit fullscreen mode

更新密码

最后,我们来创建UpdatePassword更新用户密码的函数:

  func UpdatePassword(c *gin.Context, cognito congnitoClient.CognitoInterface) error {
    token := strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
    if token == "" {
      return errors.New("token not found")
    }
    var user congnitoClient.UserLogin
    if err := c.ShouldBindJSON(&user); err != nil {
      return errors.New("invalid json")
    }
    err := cognito.UpdatePassword(&user)
    if err != nil {
      return errors.New("could not update password")
    }
    return nil
  }
Enter fullscreen mode Exit fullscreen mode

我们还强制要求在请求头中提供令牌,其余功能与我们之前已经完成的功能相同。

让我们创建最后一个端点:

  r.PATCH("user/password", func(context *gin.Context) {
        err := UpdatePassword(context, cognitoClient)
        if err != nil {
            if err.Error() == "token not found" {
                context.JSON(http.StatusUnauthorized, gin.H{"error": "token not found"})
                return
            }
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
        context.JSON(http.StatusOK, gin.H{"message": "password updated"})
    })
Enter fullscreen mode Exit fullscreen mode

我们来打电话吧:

PATCH http://localhost:8080/user/password HTTP/1.1
content-type: application/json
Authorization: Bearer token_jwt

{
  "email": "wivobi1159@bitofee.com",
  "password": "NovaSenha2@2222"
}
Enter fullscreen mode Exit fullscreen mode

现在,当您更新密码并尝试登录时,您会收到错误提示;如果您使用新密码,一切都会正常运行。

最后考虑因素

在这篇文章中,我们将简单介绍一下 Cognito,它是 AWS 众多服务之一,很多人可能并不了解它,但它对系统的演进却大有裨益。

Cognito 的实用性远不止我刚才提到的这些。虽然设置基本登录很简单,但 Cognito 的突出之处在于它已经提供了现成的账户验证系统、社交网络登录选项(如果没有 Cognito,实现起来会非常麻烦)、双因素身份验证等等,而且它还利用 AWS 安全来保护用户数据。

Cognito 的功能更多,建议查阅文档了解所有功能

存储库链接

项目仓库

请点击此处查看我博客上的文章。

订阅并接收新帖子的通知,参与互动

文章来源:https://dev.to/wiliamvj/authentication-with-golang-and-aws-cognito-577e