【问题标题】:Issue CORS preflight request with credentials使用凭据发出 CORS 预检请求
【发布时间】:2018-10-31 17:42:41
【问题描述】:

我正在使用无服务器 yml 模板将我的函数部署到 aws。以下 sn -p 显示了其中一个端点的配置,

functions:
  publish:
    handler: lambda.publish
    events:
      - http:
          method: post
          path: publish
          cors:
            origin: ${self:custom.origin.${self:custom.stage}}
            allowCredentials: true

这是我的获取请求,

fetch(`${SOME_DOMAIN}/publish`, {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(data),
    })

我正在像这样处理我的 lambda 中的响应标头,

const ALLOWED_ORIGINS = [
  'http://localhost:3001',
  'https://staging.company.com.au',
  'https://blaze-staging.company.com.au',
  'https://www.company.com.au',
  'https://blaze.company.com.au',
  'https://direct.company.com.au',
]

const origin = event.headers.origin
let headers

if (ALLOWED_ORIGINS.includes(origin)) {
  headers = {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': origin,
    'Access-Control-Allow-Credentials': true,
  }
} else {
  headers = {
    'Access-Control-Allow-Origin': 'http://localhost:3001',
  }
}

const response = {
  statusCode: 200,
  headers,
  body: JSON.stringify({ message: 'Successfully published the message.' }),
}

callback(null, response)

我无法让飞行前请求工作,因为我无法设置多个来源。如何解决这个问题?设置mode: 'no-cors' 在请求上实际上是允许来自任何域的请求。非常感谢任何帮助。

飞行前请求将显示以下错误:

无法加载https://o9a0130i2r.execute-api.us-east-1.amazonaws.com/development/publish: 对预检请求的响应未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。因此不允许使用原点“https://direct.company.com” 使用权。响应的 HTTP 状态代码为 403。如果响应不透明 满足您的需求,将请求的模式设置为“no-cors”以获取 禁用 CORS 的资源。

【问题讨论】:

  • 您的问题不清楚。您可能想使用stackoverflow.com/posts/50459481/edit 来编辑/更新您的问题并添加您在浏览器开发工具中看到的确切错误消息,当事情没有按您预期的那样工作时。 “设置多个来源”是什么意思?这与您已经使用现有的 'Access-Control-Allow-Origin': origin 代码所做的有什么不同?这会将 Access-Control-Allow-Origin 响应标头值设置为与 Origin 请求标头相同的值——如果源是允许的源——对吗?你是说代码不工作?
  • @sideshowbarker 'Access-Control-Allow-Origin': origin 没有问题。问题在于飞行前请求没有命中它由 api-gateway 处理的 lambda。我不确定如何通过它。我添加了错误信息
  • @sideshowbarker 关于“设置多个来源”,我说的是无服务器模板。你需要这个来完成飞行前的请求。我希望多个域支持带有凭据的请求。
  • 您是否阅读过docs.aws.amazon.com/apigateway/latest/developerguide/… 的文档?这似乎准确地显示了如何在 AWS API Gateway 中启用对 OPTIONS 请求的支持。您在问题中引用的错误消息的原因似乎是您的服务器正在使用 403 响应 OPTIONS 请求,因为您没有在其中启用对 OPTIONS 请求的支持。
  • 我正在使用无服务器来部署我的 lambda。我正在关注本指南 - serverless.com/blog/cors-api-gateway-survival-guide。所以需要关于无服务器框架的帮助。如果我自己创建 API,我可以解决这个问题。

标签: lambda cors aws-api-gateway serverless


【解决方案1】:

向处理 post 请求的同一个 lambda 添加一个额外的端点。

类似这样的serverless.yml

  options:
    handler: lambda.options
    events:
      - http:
          method: options
          path: publish

您可以将您的来源添加到允许的来源列表中

export const options = async (event, context, callback) => {
  const ALLOWED_ORIGINS = [
    'http://localhost:3001',
  ]

  const origin = event.headers.origin || event.headers.Origin
  let response

  if (ALLOWED_ORIGINS.includes(origin)) {
    response = {
      statusCode: 200,
      headers: {
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Allow-Origin': origin,
        'Access-Control-Allow-Credentials': true,
      },
      body: JSON.stringify({ message: 'Success' }),
    }
  } else {
    response = {
      statusCode: 403,
      headers: {
        'Access-Control-Allow-Origin': '*',
      },
      body: JSON.stringify({ message: {
        error: 'Missing Authentication token',
        origin: `Request origin is ${origin}`,
      },
      }),
    }
  }

  callback(null, response)
  return
}

现在,当浏览器发出选项请求时,我们会使用这个方法处理它,如果它来自允许的来源或错误,则返回 200。您可以根据需要自定义错误消息。

【讨论】:

  • 感谢您发布 @Mah3ndra。我也在今天早上使用 apigateway 中的自定义响应映射模板让它工作。我没有考虑创建一个单独的 lambda 来处理选项请求。这可能是比我做的更快的选择哈哈。
  • @Dan 您可以与我分享您设置 apigateway 的 serverless.yml 吗?我有同样的问题,也让他们在本地运行。提前致谢!
猜你喜欢
  • 2012-02-24
  • 2015-08-27
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
  • 2015-09-29
  • 2012-11-08
相关资源
最近更新 更多