第三十章 权限与安全
篇别:第六篇 数据安全
本章学习目标
- 从 纵深防御 串联 ACL、记录规则、字段权限、Controller。
- 了解 敏感数据加密 与 备份 的 分工(应用层 vs 存储层)。
- 配置 审计 与 失败登录 的可观测性。
- 落实 SQL 注入、CSRF、XSS 在 Odoo 自定义代码中的 检查点。
导读:安全不是「装个 HTTPS」
Odoo 同时暴露 JSON-RPC、HTTP 路由、QWeb 报表、网站前端。一层疏漏(例如 Controller 手写 SQL、csrf=False 滥用、t-raw)就可能 跨层放大。本章与 第七章 的 ir.model.access / ir.rule 呼应,并补上 Web 与数据落盘 维度。
30.1 权限控制
30.1.1 知识要点
- ACL(
ir.model.access):模型级 CRUD;无读权限则 ORM 不可见(规则之前先过 ACL)。 - 记录规则(
ir.rule):domain_force 过滤行;globalvs 组绑定;多规则 AND 组合。 - 字段级:
groups=在字段定义上;Odoo 19 字段访问相关能力见官方 Security 文档。 - API 层:
check_access、has_access、_filtered_access等(版本差异以文档为准)用于 显式校验。 - 顺序:可记 「认证用户 → ACL → Record Rules → 业务代码」;
sudo()绕过规则,仅限受控内部逻辑。
30.1.2 案例
口述画图题(练习用):从 /web/dataset/call_kw 到 record.write,标出 session 用户 → env → check_access → rule SQL。
30.1.3 截图占位

30.1.4 本节练习
- 案例:画出 「用户请求 → ACL → Rule → record」 判断顺序(可用列表或方框图)。
- 简答:
sudo()后 仍受 ACL 吗?(以你使用的版本行为为准,查阅后作答。)
参考答案提示:2. sudo() 典型为 超级用户上下文,通常 绕过规则;具体以源码 sudo 实现为准。
30.2 数据加密
30.2.1 知识要点
- 传输:HTTPS 终止于 反向代理;HSTS、证书轮换。
- 静态敏感字段:密码类用 哈希;对称密钥字段可用
fields.Char+ 加密存储 或 外部 KMS(自定义)。 - 附件:filestore 在磁盘;备份需 同时备份 DB + filestore。
- 数据库:透明磁盘加密(TDE)、卷加密 与 应用层字段加密 互补,不是替代关系。
30.2.2 案例
备份脚本检查清单:pg_dump 时间戳、filestore rsync、恢复演练季度表。
30.2.3 本节练习
- 简答:filestore 与 数据库备份 的加密策略各举 一条。
- 判断:仅加密数据库文件即可保证 附件 不外泄。( )
参考答案提示:2. 错;附件可能在 filestore。
30.3 审计日志
30.3.1 知识要点
ir.logging:部分 错误与系统事件;业务审计常需 自定义模型 或 外部 SIEM。- 登录:失败次数、来源 IP;与 fail2ban 等联动。
- 数据变更:mail.thread 的 消息 可作为一种 业务级审计;高合规场景需 不可篡改链(外挂)。
30.3.2 案例
在 测试库 故意 输错密码,在 日志或设置 → 技术 中定位 失败记录(以部署为准)。
30.3.3 截图占位

30.3.4 本节练习
- 实操:在 测试环境 记录 一次失败登录 的 日志行(打码敏感信息)。
- 简答:业务审计表 与 Web 服务器访问日志 各解决什么问题?
参考答案提示:2. 前者追踪 谁改了哪条业务记录;后者追踪 请求与会话层攻击面。
30.4 SQL 注入防护(新增)
30.4.1 知识要点
- 禁止 字符串拼接 用户输入 进 SQL。
- 参数化:
cr.execute("... WHERE x = %s", (val,))。 - Odoo 19:
odoo.tools.SQL组合片段时 遵循文档,避免 误判为已转义。 - ORM:优先
search;必须原生 SQL 时 白名单列名。
30.4.2 案例
# 危险
# self.env.cr.execute("SELECT id FROM x WHERE name = '%s'" % name)
# 较安全
self.env.cr.execute("SELECT id FROM x WHERE name = %s", (name,))
30.4.3 本节练习
- 改错:找出项目中 一处 字符串拼接 SQL 并改为 参数化。
- 简答:ORM 的 domain 来自 前端 时仍需注意什么?
参考答案提示:2. 恶意 domain / 字段名;应对 不可信输入 做 白名单或服务端重建 domain。
30.5 CSRF 与 XSS 防护(新增)
30.5.1 知识要点
- CSRF:type='http'` 路由默认 校验 token;
csrf=False仅用于 已签名 API、公开 webhook 等,并需 替代防护(签名、IP 限制)。 - JSON-RPC:机制与 表单 POST 不同;查阅当前版本 文档 理解 会话与同源策略。
- XSS:QWeb
t-esc默认转义;t-out(新版本)按文档使用;避免t-raw处理用户 HTML,除非 消毒库 可控。
30.5.2 案例
from odoo import http
class MyController(http.Controller):
@http.route("/my/ping", type="http", auth="public", website=True, csrf=False)
def ping(self, **kw):
# 必须有其它校验,例如 HMAC query token
return request.make_json_response({"ok": True})
30.5.3 截图占位

30.5.4 本节练习
- 简答:JSON-RPC 与 表单 POST 的 CSRF 差异 一句话。
- 判断:所有 public 路由都应设
csrf=False方便对接。( )
参考答案提示:2. 错。
本章综合练习
- 红队视角:攻击 自定义 Controller 的三条路径(SQL、越权、CSRF 各一)。
- 合规:GDPR 删除请求 在 Odoo 中的处理要点(匿名化、备份、日志 各提一条)。
- 综合:普通用户 在列表能看到 他人订单号 但 打不开表单——可能是哪两类配置问题?
- 实操:用 测试用户 验证
ir.ruledomain 与groups组合是否符合产品说明。
本章对应白皮书目录:第三十章 权限与安全。