Symfony 5与React.js集成时遭遇CORS策略拦截问题
使用Symfony和React.js开发REST API,认证功能正常且能获取用户信息,但调用接口获取数据时遇到CORS错误:
从源'null'访问'myapi/users'已被CORS策略阻止:对预检请求的响应未通过访问控制检查:不具备HTTP ok状态。
React请求代码
const fetchData = () => { fetch(`${apiKey}/users`, { method: "GET", headers: { "X-AUTH-TOKEN": jwtToken, "Content-Type": "application/json", }, }) .then((response) => response.json()) .then((data) => { console.log(data); }) .catch((error) => console.log(error)); };
Symfony的Nelmio CORS配置(nelmio_cors.yaml)
nelmio_cors: defaults: origin_regex: false allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] allow_methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] allow_headers: ['Accept','Authorization','Cache-Control','Content-Type','DNT','If-Modified-Since', 'Keep-Alive','Origin','User-Agent','X-Requested-With','X-AUTH-TOKEN'] expose_headers: ['Link', 'Authorization', 'X-AUTH-TOKEN'] max_age: 3600 allow_credentials: true skip_same_as_origin: true paths: '^/': allow_credentials: true origin_regex: true allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] allow_headers: ['*'] allow_methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] max_age: 3600
.env配置
CORS_ALLOW_ORIGIN=.
修正CORS_ALLOW_ORIGIN配置
当前.env里的CORS_ALLOW_ORIGIN=.是无效配置,若要允许所有合法来源,改为CORS_ALLOW_ORIGIN=^https?://.*$;若指定前端域名(如React开发服务器地址http://localhost:3000),则直接写CORS_ALLOW_ORIGIN=http://localhost:3000,多域名场景可使用正则匹配。添加OPTIONS方法支持
预检请求默认使用OPTIONS方法,当前配置的allow_methods未包含该方法,会导致预检请求被拒绝。修改defaults和paths下的allow_methods,添加OPTIONS:allow_methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']确认NelmioCorsBundle注册状态
检查config/bundles.php中是否存在Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],若缺失则添加,随后清除Symfony缓存:php bin/console cache:clear排查前端请求源问题
错误中显示源为null,通常是因为前端以file://协议运行(直接打开本地HTML文件)或apiKey变量为空。确保前端在http:///https://协议下运行(如React开发服务器localhost:3000),且apiKey正确指向Symfony API地址。手动测试预检请求
使用curl发送OPTIONS请求验证配置:curl -X OPTIONS -H "Origin: http://localhost:3000" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-AUTH-TOKEN,Content-Type" http://your-api-domain/users若返回200 OK则CORS配置生效;若返回4xx/5xx,查看Symfony日志
var/log/dev.log,排查是否被路由、防火墙或其他中间件拦截。
内容的提问来源于stack exchange,提问作者haroun bouriga

