ses.sendmail() 给出 CORS 错误。响应中的“Access-Control-Allow-Origin”标头不得为通配符“*”。凭证模式为“包含”

Posted

技术标签:

【中文标题】ses.sendmail() 给出 CORS 错误。响应中的“Access-Control-Allow-Origin”标头不得为通配符“*”。凭证模式为“包含”【英文标题】:ses.sendmail() gives CORS error. 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'..credentials mode is 'include' 【发布时间】:2021-05-09 08:11:36 【问题描述】:

我已经坚持了 4 天了。我真的需要一些见解。

我在 AWS 上部署了一个无服务器 express 应用程序。我从 S3 为我的前端提供服务,从 lambda 提供后端服务。 API 网关具有代理,如下面的 serverless.yml 所示。

我还使用 Cloudfront 将我的域 (https://my.domain.com.au) 映射到 S3 存储桶原始 URL。

正常的 GET POST PUT DELETE 请求工作正常。但是当我尝试从 Lambda 访问任何其他 AWS 服务时,我会收到以下 CORS 错误。

Access to XMLHttpRequest at 'https://0cn0ej4t5w.execute-api.ap-southeast-2.amazonaws.com/prod/api/auth/reset-password' from origin 'https://my.domain.com.au' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

我的用例是从我尝试使用的应用发送邮件。

ses.sendEmail(params).promise();

这给了我同样的错误。所以我尝试通过 lambda 调用它,同样的错误。现在我正在尝试将邮件内容推送到 S3 并使用触发器从 lambda 发送邮件,但这给了我同样的错误。

问题似乎不在代码上,因为它在本地环境中完美运行。但是,我不想留下任何石头。

由于我的 lambda 在 VPC 中,我使用了互联网网关并尝试设置私有链接。

无服务器.yml

service: my-api

# plugins 
plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-dotenv-plugin

# custom for secret inclusions
custom:
  stage: $opt:stage, self:provider.stage
  serverless-offline:
    httpPort: 5000
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: # enable auto-packing of external modules
      forceInclude:
        - mysql
        - mysql2 
        - passport-jwt
        - jsonwebtoken
        - moment
        - moment-timezone
        - lodash

# provider
provider:
  name: aws
  runtime: nodejs12.x
  # you can overwrite defaults here
  stage: prod
  region: $env:AWS_REGION_APP
  timeout: 10
  iamManagedPolicies:
    - 'arn:aws:iam::777777777777777:policy/LambdaSESAccessPolicy'
  vpc:
    securityGroupIds:
      - $env:AWS_SUBNET_GROUP_ID
    subnetIds:
      - $env:AWS_SUBNET_ID1
      - $env:AWS_SUBNET_ID2
      - $env:AWS_SUBNET_ID3
  environment:
    /// env variables (hidden)
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - s3:*
        - ses:*
        - lambda:*
      Resource: '*'

# functions
functions:
  app:
    handler: server.handler
    events:
      - http:
          path: /
          method: ANY
      - http:
          path: /proxy+
          method: ANY
          cors:
            origin: $env:CORS_ORIGIN_URL
            allowCredentials: true
            headers: 'Access-Control-Allow-Origin, Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization'
            method: ANY

# you can add CloudFormation resource templates here
resources:
  # API Gateway Errors
  - $file(resources/api-gateway-errors.yml)
  # VPC Access for RDS
  - $file(resources/lambda-vpc-access.yml)

我也配置了响应头:

app.use(function(req, res, next) 
    res.header("Access-Control-Allow-Origin", process.env.CORS_ORIGIN_URL);
    res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization");
    res.header("Access-Control-Allow-Credentials", "true");
    res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,DELETE");
    next();
);

【问题讨论】:

【参考方案1】:

我实际上和你有同样的错误,但我已经弄清楚了。

我只是粘贴我的代码,因为你没有显示你的 lambda 函数是什么样子的。

我也知道已经过去了两周...所以希望这对将来的人有所帮助。

CORS 错误是服务器端的,我相信您知道。 AWS SES 的问题是您必须正确处理 lambda,否则即使您有正确的标头,它也会给您一个 cors 错误。

首先要做的事情...我认为您的 api 网关中没有 OPTIONS 方法...尽管我不确定是否可以替代任何方法。

第二个是我的代码: 我检查我得到的 http 方法,然后我根据它做出响应。我收到一个帖子事件,正文中有一些细节。您可能希望将 finally 块更改为其他内容。 OPTIONS 对 CORS 很重要,它让浏览器知道可以发送 POST 请求(或者至少我是这么认为的)

var ses = new AWS.SES();

var RECEIVER = 'receiver@gmail.com';
var SENDER = 'sender@gmail.com';

exports.handler = async(event) => 

  let body;
  let statusCode = '200';
  const headers = 
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET,DELETE,POST,PATCH,OPTIONS',
    'Access-Control-Allow-Credentials': true,
    'Access-Control-Allow-Headers': 'access-control-allow-credentials,access-control-allow-headers,access-control-allow-methods,Access-Control-Allow-Origin,authorization,content-type',
    'Content-Type': 'application/json'
  ;
  console.log(event);

  try 
    switch (event.httpMethod) 
      case 'POST':
        event = JSON.parse(event.body);
        var params = 
          Destination: 
            ToAddresses: [
              RECEIVER
            ]
          ,
          Message: 
            Body: 
              html: 
                Data: html(event.name, event.phone, event.email, event.message), // 'Name: ' + event.name + '\nPhone: ' + event.phone + '\nEmail: ' + event.email + '\n\nMessage:\n' + event.message,
                Charset: 'UTF-8'
              
            ,
            Subject: 
              Data: 'You Have a Message From ' + event.name,
              Charset: 'UTF-8'
            
          ,
          Source: SENDER
        ;
        await ses.sendEmail(params).promise();
        break;
      case 'OPTIONS':
        statusCode = '200';
        body = "OK";
        break;
      default:
        throw new Error(`Unsupported method "$event.httpMethod"`);
    
  
  catch (err) 
    statusCode = '400';
    body = err.message;
  
  finally 
    body = "\"result\": \"Success\""
  
 
  console.log(
    statusCode,
    body,
    headers,
  )
  return 
    statusCode,
    body,
    headers,
  ;


【讨论】:

以上是关于ses.sendmail() 给出 CORS 错误。响应中的“Access-Control-Allow-Origin”标头不得为通配符“*”。凭证模式为“包含”的主要内容,如果未能解决你的问题,请参考以下文章

谷歌分析跟踪代码给出 CORS 错误

React Ajax Request 给出 CORS 错误但返回数据

在 Firefox 上,CORS 请求给出错误“:”(冒号)

对 Url 的发布请求给出了被 cors 策略阻止的错误 [重复]

从 Angular 9 调用 AWS api 给出 cors 错误

React w/Kubernetes 部署的 API 给出了 cors 错误