在上几篇文章介绍了如何注册,配置AWS Cognito User Pool,用户登录,Cognito中的Session,如何注销用户的登录,实现更改密码功能,如何Cognito中的用户自定义属性。下面介绍如何通过AWS Cognito UserPool来保护APIGateway。

AWS Cognito系列教程:
- React+AWS Cognito教程一:创建User Pool并实现用户注册及用户登录
- React+AWS Cognito教程二:Cognito中的Session及注销登录
- React+AWS Cognito教程三:在Cognito中更改密码
- React+AWS Cognito教程四:使用Cognito中的自定义属性
- React+AWS Cognito教程五:通过AWS Cognito UserPool保护APIGateway
- React+AWS Cognito教程六:Cognito内置的OAuth支持-使用Google登录
- Cognito中的细粒度用户访问授权
生成Lambda
首先通过serverless生成一个项目:
mkdir demo
cd demo
sls create --template aws-nodejs
添加依赖:
npm i lodash
更新serverless.yml:
service: random-number-service
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs14.x
region: eu-west-1
lambdaHashingVersion: 20201221
functions:
randomAPI:
handler: handler.random
events:
- http:
path: /random_number
method: get
cors: true
更新handler.js:
'use strict';
const _ = require("lodash");
module.exports.random = async (event) => {
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(
{
random_number: _.random(10)
},
null,
2
),
};
};
部署:
sls deploy
然后通过浏览器访问API地址,就可以得到类似这样的输出:
{
"random_number": 4
}
在AWS配置Lambda/APIGateway和Cognito之间的授权
以下操作也可以通过serverless来定义,但为了直观,这里通过手工操作。
创建authorizer
选择AWS API Gateway -> APIs -> dev-random-number -> Authorizers -> “Create New Authorizer”。
进行如下配置后创建Authorizer:

为API Gateway添加authorizer
选择API Gateway后单击要被保护的方法:

然后选择刚刚创建的Authorizer:

都修改完毕后需要重新部署API:

测试受保护的API
现在直接访问这个API的话会返回非授权访问的错误:

也就是说,需要找到这个token并将其加入header后才能成功调用API。
使用JWT token:
更新Accounts.js
更新Accounts.js,在调用resolve方法前:
const token = session.getIdToken().getJwtToken()
resolve({
user,
headers: {
Authorization: token,
},
...session,
...attributes
});
人工测试
也可以加一个console.log语句输出token的值,之后拿着token就可以在Postman中测试了:

在React中访问受保护的API
添加依赖:
npm i axios
添加一个文件RandomNumber.js:
import React, { useState, useContext } from 'react'
import axios from 'axios'
import { AccountContext } from './Accounts'
export default () => {
const [number, setNumber] = useState(0)
const { getSession } = useContext(AccountContext)
const fetchNumber = () => {
getSession().then(async ({ headers }) => {
const url = 'https://XXXXXX.execute-api.eu-west-1.amazonaws.com/dev/random_number'
const resp = await axios.get(url, { headers })
setNumber(resp.data["random_number"])
})
}
return (
<div>
<div>Current number: {number}</div>
<button onClick={fetchNumber}>Next number</button>
</div>
)
}