React.js对接Odoo设置auth=user并开启CORS时跨域报错如何解决
问题根因
你遇到的跨域报错本质是Odoo对auth="user"类型的接口,默认不会对CORS预检的OPTIONS请求做放行处理:OPTIONS请求本身不会携带任何用户认证信息,Odoo会直接拦截该请求并返回303重定向到登录页,而浏览器规范明确禁止预检请求出现重定向,因此直接抛出跨域错误,和你后续POST请求携带的session_id无关。
另外Odoo接口上配置的cors="*"参数仅对实际业务请求生效,不会作用于OPTIONS预检请求,这也是你配置了CORS仍报错的核心原因。
解决方案
以下方案无需修改Odoo核心代码,全程在自定义模块和前端配置即可落地:
1. 新增全局OPTIONS请求处理控制器
在你的自定义Odoo模块的控制器文件中添加如下代码,单独处理所有预检请求,不做登录校验,直接返回合规的CORS响应头:
from odoo import http from odoo.http import request class CORSPreflightController(http.Controller): # 可根据业务需求缩小路由匹配范围,比如仅匹配你自己的业务接口前缀 /api/<path:path> @http.route(['/<path:path>'], type='http', auth="none", cors="*", methods=['OPTIONS'], csrf=False) def handle_options(self, path, **kw): headers = { 'Access-Control-Allow-Origin': request.httprequest.headers.get('Origin', '*'), 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE', 'Access-Control-Allow-Headers': 'Content-Type, X-Openerp-Session-Id, Accept', 'Access-Control-Allow-Credentials': 'true', } return request.make_response('', headers=headers, status=200)
2. 保留原有业务接口配置
你之前写的业务接口无需修改,保持auth="user", cors="*"的配置即可。
3. 确认前端session_id有效性
你请求头中携带的X-Openerp-Session-Id必须是通过Odoo官方认证接口获取的有效会话ID,获取逻辑参考:
import axios from 'axios' import Cookies from 'js-cookie' // 调用Odoo登录接口获取session_id axios.post('http://localhost:8069/web/session/authenticate', { jsonrpc: '2.0', params: { db: '你的Odoo数据库名称', login: '用户账号', password: '用户密码' } }, { headers: { "Content-Type": "application/json" } }).then(res => { if (res.data.result) { // 持久化存储有效session_id Cookies.set('session_id', res.data.result.session_id) // 全局挂载axios请求头 axios.defaults.headers.common['X-Openerp-Session-Id'] = res.data.result.session_id } })
4. 可选优化:全局配置axios
统一配置所有请求的公共头,避免每个接口重复配置:
axios.defaults.headers.common['Content-Type'] = 'application/json' axios.defaults.headers.common['Accept'] = 'application/json' // 若你使用Cookie自动携带session的方案,可额外开启以下配置 // axios.defaults.withCredentials = true
注意事项
- 若Odoo部署了多数据库,启动时请添加参数
--db-filter=你的数据库名,避免会话校验失败 - 生产环境建议把OPTIONS路由的匹配范围缩小到你的业务接口前缀,避免影响Odoo原生功能的正常使用
- 生产环境不要把
Access-Control-Allow-Origin设为*,请替换为你的React应用正式域名
内容的提问来源于stack exchange,提问作者José Vicente Matos Ramonez
相关产品推荐
相关产品推荐

