在本模块中,您将配置 Amazon Cognito,以便在应用程序中用作身份验证提供程序。Amazon Cognito 是一个全托管的身份验证提供程序,支持用户注册、验证、登录等功能。
Amazon Cognito 包含两个不同的组件:User Pools(用户池)和 Identity Pools(身份池)。用户池是标准的用户目录,用户可以通过 Amazon Cognito 或第三方身份(如 Facebook)登录。身份验证成功后,用户会收到相应令牌(例如访问令牌或身份令牌),可用于访问后端资源。
相比之下,通过身份池,用户可以获得临时的 AWS 凭证来访问 AWS 资源。身份池可以用来提供对 AWS Lambda 函数、Amazon DynamoDB 表或其他资源的有限的直接访问。
本教程将使用 Amazon Cognito 用户池。我们允许用户通过我们的应用程序注册。注册后,用户可以通过客户端登录并获取身份令牌。该身份令牌可以作为请求标头传递给应用程序,用于用户身份验证。
在接下来的步骤中,您将创建一个 Amazon Cognito 用户池。然后创建一个客户端应用程序来访问该用户池。最后,我们来看一些与用户池交互的示例代码。
完成时间
10 分钟
-
步骤 1:创建 Amazon Cognito 用户池
用户池是一个用户目录,用户和用户组的所有管理操作都在该池中进行。创建用户池时,您需要为其指定规则,包括密码策略和必填属性。
在 scripts/ 目录中,有一个名为 create-user-pool.sh 的文件。该文件内容如下所示:
USER_POOL_ID=$(aws cognito-idp create-user-pool \ --pool-name recommendation-users \ --policies ' { "PasswordPolicy": { "MinimumLength": 8, "RequireUppercase": true, "RequireLowercase": true, "RequireNumbers": true, "RequireSymbols": false } }' \ --query 'UserPool.Id' \ --output text) echo "User Pool created with id ${USER_POOL_ID}" echo "export USER_POOL_ID=${USER_POOL_ID}" >> env.sh
该脚本使用 AWS 命令行界面 (AWS CLI) 创建用户池。其中将用户池 (USER_POOL) 命名为 recommendation-users,同时定义了密码策略。脚本要求密码长度至少为 8 个字符,且必须包含大写字母、小写字母和数字。
您可以运行以下命令来执行该脚本,创建用户池:
bash scripts/create-user-pool.sh
您应当会看到以下输出结果:
User Pool created with id <user-pool-id>
下一步,我们将创建一个客户端来访问该用户池。
-
步骤 2:创建用户池客户端
用户池配置完成后,接下来需要创建一个 User Pool Client(用户池客户端)。用户池客户端用于调用用户池的非身份验证方法,例如用户注册和登录。
我们后端的 Node.js 应用程序将使用该用户池客户端。要注册或登录,用户向应用程序发送包含相关属性的 HTTP POST 请求。应用程序使用用户池客户端,将这些属性转发至 Amazon Cognito 用户池。然后,应用程序返回相应的数据或错误消息。
在 scripts/ 目录中,有一个名为 create-user-pool-client.sh 的文件,用于创建用户池客户端。此文件的内容如下所示:
source env.sh CLIENT_ID=$(aws cognito-idp create-user-pool-client \ --user-pool-id ${USER_POOL_ID} \ --client-name recommendation-backend \ --no-generate-secret \ --explicit-auth-flows ADMIN_NO_SRP_AUTH \ --query 'UserPoolClient.ClientId' \ --output text) echo "User Pool Client created with id ${CLIENT_ID}" echo "export COGNITO_CLIENT_ID=${CLIENT_ID}" >> env.sh
该脚本将为新创建的用户池创建一个用户池客户端。其中的 ADMIN_NO_SRP_AUTH 是一种可用于服务器端应用程序的身份验证流程。由于我们使用的是服务器端流程,所以不需要客户端流(例如移动设备或单页应用程序)中使用的 Client Secret(客户端密钥)。
运行该脚本,使用以下命令创建用户池客户端:
bash scripts/create-user-pool-client.sh
您应当会看到以下输出结果:
User Pool Client created with id <client-id>
在本模块的最后一步,我们来学习一下应用程序中用到的身份验证相关代码。
-
步骤 3:查看身份验证代码
现在用户池和访问该池的客户端都已创建完毕。让我们来看看如何在应用程序中使用 Amazon Cognito。
在项目的 application/ 目录中,有一个名为 auth.js 的文件。该文件包含一些用于应用程序身份验证的辅助函数。文件中有三个核心函数。下面我们来逐一介绍。
第一个函数是 createCognitoUser,用于在 Amazon Cognito 中注册新用户。此函数如下所示:
const createCognitoUser = async (username, password, email) => { const signUpParams = { ClientId: process.env.COGNITO_CLIENT_ID, Username: username, Password: password, UserAttributes: [ { Name: 'email', Value: email } ] } await cognitoidentityserviceprovider.signUp(signUpParams).promise() const confirmParams = { UserPoolId: process.env.USER_POOL_ID, Username: username } await cognitoidentityserviceprovider.adminConfirmSignUp(confirmParams).promise() return { username, email } }
该函数使用上一步设置的 Amazon Cognito 客户端 ID,以及用户提供的用户名、密码和电子邮件来创建新用户。另外,函数还将立即对用户进行确认,以便其可以直接登录。通常情况下,应用程序应包含一个验证流程来校验用户的邮箱和/或手机号码,以获取用户的联系方式。不过此内容不在本教程讨论范围之内,您只需自动确认新用户即可。
第二个核心方法是 login 函数,在已注册用户登录时用于身份验证。代码如下所示:
const login = async (username, password) => { const params = { ClientId: process.env.COGNITO_CLIENT_ID, UserPoolId: process.env.USER_POOL_ID, AuthFlow: 'ADMIN_NO_SRP_AUTH', AuthParameters: { USERNAME: username, PASSWORD: password } } const { AuthenticationResult: { IdToken: idToken } }= await cognitoidentityserviceprovider.adminInitiateAuth(params).promise() return idToken }
和 createCognitoUser 函数类似,我们使用客户端 ID 和提供的参数调用 Amazon Cognito。Amazon Cognito 的 adminInitiateAuth 方法用于用户身份验证,如果验证通过,就返回令牌。我们使用 IdToken(身份令牌)进行身份验证,所以用户登录成功时返回的就是身份令牌。
最后是 verifyToken 函数。此函数的内容如下所示:
const verifyToken = async (idToken) => { function getKey(header, callback){ client.getSigningKey(header.kid, function(err, key) { var signingKey = key.publicKey || key.rsaPublicKey; callback(null, signingKey); }); } return new Promise((res, rej) => { jwt.verify(idToken, getKey, {}, function(err, decoded) { if (err) { rej(err) } res(decoded) }) }) }
该函数验证请求中传入的身份令牌。Amazon Cognito 提供的身份令牌是 JSON Web 令牌 (JWT)。verifyToken 函数确认令牌是由受信任的源签发的,并验证用户身份。在需要身份验证的 Endpoint(端点)中使用此函数,确保发出请求的用户有访问权限。
在接下来的模块中,我们会在后端应用程序中用到这三个身份验证函数。
在本模块中,我们创建并配置了 Amazon Cognito 用户池及其客户端。我们还了解了一些辅助函数,用于与 Amazon Cognito 用户池交互,实现用户注册、登录和验证。
在下一个模块中,我们将使用 AWS Lambda 和 Amazon API Gateway 等无服务器技术来部署后端应用程序。