You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用带CORS与auth=user的Odoo端点遇CORS重定向错误求助

问题:Odoo带auth=user的端点触发CORS预请求重定向错误

我需要调用一个配置了CORS和auth='user'的Odoo端点,但始终收到CORS错误,以下是相关配置和代码:

已配置的目标端点

@http.route('/endpoint', type='json', cors='http://127.0.0.1:5173', auth='user', csrf=False, methods=['OPTIONS', 'POST'])
def endpoint(self):
    return {'test'}

Axios调用代码

axios.post('http://127.0.0.1:8069/endpoint', {
    jsonrpc: "2.0",
    params: {},
}, {
    headers: {"Content-Type": "application/json"},
    withCredentials: true,
})
.then(content => {
    console.log(content.data)
})
.catch(error => alert(JSON.stringify(error)))

收到的错误信息

Access to XMLHttpRequest at 'http://127.0.0.1:8069/endpoint' from origin 'http://127.0.0.1:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.

已正常工作的登录接口

登录接口配置和调用都没问题,代码如下:

登录端点代码

@http.route('/login', type='json', cors='http://127.0.0.1:5173', auth='none', csrf=False, methods=['OPTIONS', 'POST'])
def login(self, db, login, password):
    http.request.session.authenticate(db, login, password)
    return http.request.env['ir.http'].session_info()

登录接口Axios调用

axios.post('http://127.0.0.1:8069/login', {
    jsonrpc: "2.0",
    params: {
        db: "db_name",
        login: email,
        password: password
    },
}, {
    headers: {"Content-Type": "application/json"},
    withCredentials: true,
})
.then(content => {
    console.log(content.data)
})
.catch(error => alert(JSON.stringify(error)))

解决方案

问题根源

当端点设置auth='user'时,Odoo会拦截未携带有效会话的请求,自动重定向到登录页面。但浏览器发送的OPTIONS预请求不会携带会话凭证(即使开启withCredentials: true),导致预请求被重定向,而CORS规则明确禁止预请求被重定向,因此触发错误。

修复方案:拆分OPTIONS与POST请求的认证规则

将OPTIONS请求单独配置为auth='none',确保预请求能正常通过,同时保持POST请求的用户认证要求。

方案1:拆分两个路由

# 处理POST请求,保持用户认证
@http.route('/endpoint', type='json', cors='http://127.0.0.1:5173', auth='user', csrf=False, methods=['POST'])
def endpoint(self):
    return {'test': 'success'}

# 单独处理OPTIONS预请求,无需认证
@http.route('/endpoint', type='http', cors='http://127.0.0.1:5173', auth='none', csrf=False, methods=['OPTIONS'])
def endpoint_options(self):
    headers = {
        'Access-Control-Allow-Origin': 'http://127.0.0.1:5173',
        'Access-Control-Allow-Methods': 'POST, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Allow-Credentials': 'true'
    }
    return request.make_response('', headers=headers)

方案2:在同一个路由中处理两种请求

@http.route('/endpoint', type='json', cors='http://127.0.0.1:5173', auth='none', csrf=False, methods=['OPTIONS', 'POST'])
def endpoint(self):
    # 处理OPTIONS预请求
    if request.method == 'OPTIONS':
        headers = {
            'Access-Control-Allow-Origin': 'http://127.0.0.1:5173',
            'Access-Control-Allow-Methods': 'POST, OPTIONS',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Credentials': 'true'
        }
        return request.make_response('', headers=headers)
    
    # 手动验证用户会话,替代auth='user'的自动校验
    if not request.session.uid:
        raise AccessDenied()
    
    # 业务逻辑处理
    return {'test': 'success'}

注意事项

  • 确保CORS头中的Access-Control-Allow-Origin与前端域名完全一致(包括端口)
  • 必须返回Access-Control-Allow-Credentials: true,配合前端的withCredentials: true传递会话凭证

内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 02:48:23