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

Odoo12使用PHP/JS调用search_read接口返回session expired会话过期问题

Odoo12 调用接口返回会话过期问题解决方案

问题根因

你的代码存在3个核心问题导致会话验证失败:

    1. 请求头格式错误:你定义的x-openerp-session_id : 键名和冒号之间多了多余空格,导致服务端无法识别该请求头
    1. Cookie手动拼接错误:仅手动传递sessionid字段,遗漏了Odoo会话依赖的其他Cookie属性,且容易出现格式错误
    1. 域名协议不一致:你登录接口请求用的是HTTPS协议,但Odoo返回的web.base.url是HTTP协议,说明Odoo前端配置了反向代理HTTPS卸载,会话Cookie的作用域/secure属性匹配失败,导致后续请求会话无效
      另外你提到Postman无需传session_id即可调用成功,是因为Postman之前存储了你登录Odoo后台的有效会话Cookie,清空Postman缓存和Cookie后即可复现错误

修复方案

方案1:使用curl自动管理Cookie(最稳定)

无需手动拼接请求头和Cookie,让curl自动处理登录返回的会话Cookie,代码示例如下:

// 初始化curl,配置Cookie自动存储路径
$cookieFile = tempnam(sys_get_temp_dir(), 'odoo_cookie');
$ch = curl_init();

// 1. 调用登录接口
$loginData = [
    'json-rpc' => '2.0',
    'method' => 'call',
    'params' => [
        'db' => 'xxxx',
        'login' => 'xxxx',
        'password' => 'xxxx',
        'context' => new stdClass()
    ],
    'id' => 10
];
$loginDataStr = json_encode($loginData);

curl_setopt($ch, CURLOPT_URL, 'https://xxxxxxxxxxxxx/web/session/authenticate');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $loginDataStr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($loginDataStr)
]);
// 开启Cookie自动存储和读取
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
// 忽略SSL证书验证(如果是自签证书可以开启,生产环境建议关闭)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

$loginRes = curl_exec($ch);
$loginResult = json_decode($loginRes, true);

// 2. 调用search_read接口,不需要手动传session相关头
$searchData = [
    'json-rpc' => '2.0',
    'method' => 'call',
    'params' => [
        'model' => 'res.users',
        'fields' => ["id", "name", "login"],
        'domain' => [],
        'context' => new stdClass(),
    ],
    'id' => 10,
];
$searchDataStr = json_encode($searchData);

curl_setopt($ch, CURLOPT_URL, 'https://xxxxxxxxxxxxxxxxxxxxx/web/dataset/search_read');
curl_setopt($ch, CURLOPT_POSTFIELDS, $searchDataStr);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Content-Length: ' . strlen($searchDataStr)
]);

$searchRes = curl_exec($ch);
print_r($searchRes);

// 用完删除临时Cookie文件
unlink($cookieFile);
curl_close($ch);

方案2:JS调用适配

如果用fetch/axios调用,需要做以下配置:

  1. 开启withCredentials配置,允许跨域请求携带Cookie
  2. 确保Odoo服务配置了正确的CORS规则,允许你的前端域名访问,且允许携带凭证
  3. 先调用登录接口,后续请求浏览器会自动携带会话Cookie,不需要手动拼接
    axios示例:
import axios from 'axios'

const odooAxios = axios.create({
  baseURL: 'https://你的Odoo域名',
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json'
  }
})

// 先调用登录
await odooAxios.post('/web/session/authenticate', {
  'json-rpc': '2.0',
  'method': 'call',
  'params': {
    'db': 'xxxx',
    'login': 'xxxx',
    'password': 'xxxx',
    'context': {}
  },
  'id': 10
})

// 再调用search_read,无需手动传session
const res = await odooAxios.post('/web/dataset/search_read', {
  'json-rpc': '2.0',
  'method': 'call',
  'params': {
    'model': 'res.users',
    'fields': ["id", "name", "login"],
    'domain': [],
    'context': {}
  },
  'id': 10
})
console.log(res.data)

方案3:使用XMLRPC接口(更稳定无需处理session)

Odoo官方提供的XMLRPC接口不需要处理会话,每次请求直接携带认证信息即可,适合后端服务调用场景,稳定性远高于web层的JSONRPC接口。

其他注意事项

  • 确保Odoo配置文件中设置了proxy_mode = True,适配反向代理HTTPS的场景,避免Cookie作用域错误
  • 不要在生产环境关闭SSL证书验证,避免安全风险
  • 如果是多数据库部署,确保所有请求的db参数一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:09:00