为 SAM 配置 CORS API 适用于邮递员,但不适用于 angular

问题描述

我在使用邮递员使用的相同端点在我的 angular 应用程序中注册用户时遇到问题。 Postman 工作正常,用户出现在 cognito 用户池中没问题,但是如果我尝试通过我的 angular 应用程序中的注册页面注册用户,那么我会收到 CORS 错误

enter image description here

当我查看 API 网关时,我注意到不同端点中没有选项部分,所以这可能是一个问题。

enter image description here

此外,当我部署 SAM 时,我发现没有设置授权,因此这也可能是一个因素。虽然不确定。如何配置我的 SAM 模板以使 CORS 与应用程序一起使用,而不仅仅是邮递员?感谢您的帮助!

SAM 模板

AWstemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: REST API using SAM

Globals:
  Function:
    Runtime: nodejs12.x
    Environment:
      Variables:
        TABLE_NAME: !Ref Table
    MemorySize: 128
    Timeout: 5

Resources:
  Table:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: userid
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 1
        WriteCapacityUnits: 1

  ConfirmUser:
    Type: AWS::Serverless::Function
    Properties:
      Handler: confirm.handler
      Events:
        GetUser:
          Type: Api
          Properties:
            Path: /confirm
            Method: post

  RegisterUser:
    Type: AWS::Serverless::Function
    Properties:
      Handler: register.handler
      Policies: AmazonDynamoDBFullAccess
      Events:
        GetUser:
          Type: Api
          Properties:
            Path: /register
            Method: post

  LoginUser:
    Type: AWS::Serverless::Function
    Properties:
      Handler: login.handler
      Events:
        GetUser:
          Type: Api
          Properties:
            Path: /login
            Method: post

注册.js

const AWS = require('aws-sdk');
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
global.fetch = require('node-fetch');

const UserPoolId = "<my user poolId>"
const ClientId = "<my client id>"

const poolData = {
    UserPoolId,ClientId
}

AWS.config.update({
    region: 'us-east-1'
})

async function registerUser(json) {
    const {
        email,password
    } = json

    return new Promise((resolve,reject) => {
        let attributeList = []

        attributeList.push(new AmazonCognitoIdentity.CognitoUserAttribute({ Name: "email",Value: email }));


        const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

        userPool.signUp(email,password,attributeList,null,function (err,result) {
            if (err) {
                return resolve({
                    statusCode: 500,err
                })
            }

            resolve({
                statusCode: 200,message: 'User successfully registered'
            })
        })
    })
}

exports.handler = async function (event,context,callback) {
    console.log("EVENT BODY",event.body)
    const json = JSON.parse(event.body)
    let result;
    let response;
    try {
        result = await registerUser(json);

        response = {
            statusCode: 200,body: JSON.stringify('User registered successfully'),headers: {
                "Access-Control-Allow-Origin": "*",// required for CORS support to work
                "Access-Control-Allow-Credentials": true // required for cookies,authorization headers with HTTPS 
            },};
    } catch (e) {
        response = {
            statusCode: 500,body: JSON.stringify('Failed to register user'),};
    }

    return response;

}

解决方法

我们需要一个 OPTIONS 方法返回以下三个标题以供浏览器使用以允许 CORS

Access-Control-Allow-Headers should contain all headers
Access-Control-Allow-Methods should contain all methods
Access-Control-Allow-Origin should contain the host or '*'

将以下模板添加到 SAM Globals 将为每个指向 Mock Integration 的方法添加必要的 OPTIONS 方法。

所有附加标题(如果有)都应添加到 AllowHeaders

Globals:
  Api:
    Cors:
      AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'"
      AllowOrigin: "'*'"
      AllowCredentials: "'*'"