CORS错误:如何正确配置Symfony 5以接受CORS?

4

目标

我正在尝试从Vue 3类型化前端向Symfony 5 API发送请求。使用NelmioCorsBundle,该请求可以在Insommia(postman)中使用,但在Chrome、Safari和Firefox中无法使用。

错误信息

跨域资源共享(CORS)策略阻止访问' https://localhost:8000/api/users/6' 的请求,该请求来源为'http://localhost:8080'。响应预检请求未通过访问控制检查:所请求的资源上没有出现'Access-Control-Allow-Origin'头部字段。如果一个不透明的响应完全满足您的需求,请将请求的模式设置为“no-cors”以禁用CORS并获取资源。

前端(Vue)请求:

import { onMounted, ref } from 'vue'
import { useStore } from 'vuex'

export default {
  name: 'Home',
  setup () {
    const message = ref('Please login...')
    const store = useStore()

    onMounted(async () => {
      try {
        const response = await fetch('https://localhost:8000/api/users/6', {
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include'
        })

        console.log(response)
        const user = await response.json()
        message.value = `Hello ${user.name}`
        await store.dispatch('setAuth', true)
      } catch (e) {
        console.log(e)
      }
      return {
        message
      }
    })
  }
}

Symfony 中的 NelmioCorsBundle 配置:

nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
        allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
        allow_headers: ['Content-Type', 'Authorization']
        expose_headers: ['Link']
        max_age: 3600
    paths:
        '^/': null

在 .env 文件中,CORS_ALLOW_ORIGIN 被定义为:
CORS_ALLOW_ORIGIN='^http?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'

我的尝试

  1. 我尝试在NelmioCorsBundle和index.php中设置Access-Control-Allow-Origin头部。
  2. 我尝试将allow_origin设置为'http://localhost:8080'。
  3. 我尝试在index.php文件中编写代码来设置不同的头部,但最终只是遇到了错误。
  4. 我还尝试了文档中有关如何忽略New Relic上的preflight请求的建议。但这个 FilterResponseEvent 类不存在 (所以我重新安装了NelmioCorsBundle,但没有起作用.)
3个回答

7

在与Nelmio搏斗一段时间后,我发现采用这种“贫民窟”解决方案更容易:

public/index.php

if ($_SERVER['APP_DEBUG']) {
    header('Access-Control-Allow-Origin:'.rtrim($_SERVER['HTTP_REFERER'], '/'));
} else {
    header('Access-Control-Allow-Origin:yourdomain');
}
header('Access-Control-Allow-Headers:*');
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Headers:X-Requested-With, Content-Type, withCredentials');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    die();
}

我在bootEnv行后使用这个。我正在使用Symfony 5+。


哈哈!太棒了!我现在正在尝试它。yourdomain 占位符是用于本地主机地址的吗? - Kerrial Beckett Newham
@KerrialBeckettNewham 奇怪,这可能与您的设置有关。确保 $_SERVER['HTTP_REFERER'] 的值是正确的,并且只发送一个 Access-Control-Allow-Origin: 标头。您是否禁用了以前的 nelmio 安装? - yhu420
1
我无法根据这些信息为您提供更多帮助,但如果我必须给您一个建议,那就是尽可能充分利用您的开发工具来了解您所遇到问题的根本原因 :) - yhu420
是的,我已经找出问题了,而且它相当愚蠢。如果本地 Web 服务器使用 --allow-http 标志运行,则一切都按预期功能。完整命令为 symfony server:start --allow-http。然而,这并没有回答如何正确设置它的问题。 :) - Kerrial Beckett Newham
显示剩余3条评论

2

你好,这段代码很好地运行了,并且我在使用ReactJs中的axios作为前端。

nelmio_cors.yaml

nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['*']
        allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
        allow_headers: ['*']
        expose_headers: ['Link']
        max_age: 3600
    paths:
        '^/': ~

.env

###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=^.*$
###< nelmio/cors-bundle ###

1

你好,你能否尝试在NelmioCorsBundle中将路径从'^/'更改为'^/api/',并按照此示例添加此配置:

nelmio_cors:
    defaults:
        origin_regex: true
        allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
        allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
        allow_headers: ['Content-Type', 'Authorization']
        expose_headers: ['Link']
        max_age: 3600
    paths:
        '^/api/':
            allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
            allow_headers: ['X-Custom-Auth', 'Content-Type', 'Authorization', 'Location']
            allow_methods: ['POST', 'PUT', 'GET', 'DELETE', 'OPTION']
            expose_headers: ['Link', 'Location']
            max_age: 3600

谢谢,我之前尝试过这个方法(重新安装了NelmioCorsBundle,因此nelmio_cors.yaml是默认的),现在又尝试了一遍。但是没有任何改变。:'( - Kerrial Beckett Newham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接