ses.sendmail() 给出 CORS 错误。响应中的"访问控制允许源"标头不得为通配符"*"。凭据模式为"包含"



我已经被困了4天了。我真的需要一些见解。

我有一个部署在AWS上的无服务器express应用程序。我从S3服务我的前端和后端从lambda。API网关具有代理,如无服务器所示。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中,我已经使用了互联网网关并尝试设置私有链接。

Serverless.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();
});

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

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

我也知道已经两个星期了…所以希望这对将来的人有所帮助。

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

重要的是…我不认为你在api网关中有OPTIONS方法…虽然我不确定是否有任何可以作为替代品。

下面是我的代码:我检查我得到的是哪个http方法,然后基于它响应。我正在接收一个post事件和一些细节进来的身体。你可能想把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 + 'nnMessage: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,
};
}

最新更新