先说结论
Odoo 的考勤 kiosk 不是“做个公开页面,点一下就打卡”。
从 /home/ubuntu/odoo-temp/addons/hr_attendance/controllers/main.py 和相关模型能看出,官方做的是四层控制:
- 公司级 token:先限定这台 kiosk 属于哪家公司
- 员工识别方式:条码或手动选择员工
- 可选 PIN:在人被选中后再做二次确认
- 设备与地理信息:把打卡来源记录成后续可审计的信息
所以它真正解决的问题是:
如何在公共设备上做快速打卡,同时尽量别让任何人都能替别人签到。
第一层:token 决定的是公司范围,不是员工身份
_get_company(token) 会先用 attendance_kiosk_key 找公司。
这说明 kiosk URL 的 token 不是用户令牌,也不是员工令牌,而是:
- 这台终端属于哪个公司
- 后续能看到哪家公司员工
- 后续扫码或手选时,员工必须属于这家公司
所以 token 的作用是 圈定场景边界,不是完成身份认证本身。
第二层:员工识别有两条路,但风险不同
controller 里有两种核心入口:
attendance_barcode_scannedmanual_selection
条码模式的心智是:
- 终端看不到太多员工列表
- 员工自己出示 badge/barcode
- 更适合现场快速吞吐
手动选择模式则更偏:
- 前台、门岗、共用设备
- 可以从员工列表中选人
- 如果没有额外校验,更容易被冒签
所以你不能把这两种入口当成同等安全强度。
第三层:PIN 为什么不是“登录密码简化版”,而是 kiosk 第二因子
manual_selection() 里只有在:
- 公司允许不用 PIN,或者
- 员工
pin与输入值匹配
才会真正执行 _attendance_action_change()。
这说明 PIN 的定位不是通用账号密码,而是:
- 在公共终端上
- 员工被识别或被点选之后
- 再补一层“这人真的是本人”的确认
所以 PIN 更像现场二次确认,而不是账号体系替身。
第四层:为什么 kiosk 页面还要强制退出当前会话
kiosk_mode_menu 和 open_kiosk_mode() 里都处理了 session logout / password 检测。
这里的核心逻辑非常现实:
- kiosk 设备通常放在公共区域
- 如果管理员刚配置完就直接离开
- 浏览器里可能残留后台登录态
所以官方宁可多做一步自动退出,也不愿让公共屏幕顺手变成后台入口。
这是典型的“便利性输给边界安全”的设计。
第五层:设备追踪不是为了花哨,而是为了事后审计
_get_geoip_response() 会把:
- mode(kiosk / systray)
- location
- latitude / longitude
- ip_address
- browser
一起带进打卡动作。
也就是说,Odoo 不只是记“这人打了卡”,还在记:
- 从哪种入口打的
- 大概从哪儿打的
- 设备和浏览器痕迹是什么
这些信息不一定天天用,但一旦有人争议“不是我打的”“为什么这次算 kiosk 打卡”,它就是排错依据。
第六层:条码、PIN、设备追踪三者各防什么
很多人会把它们都叫“安全措施”,但其实防的不是同一类风险。
- token:限制公司范围
- barcode:提升识别效率
- PIN:防手选或代签
- device tracking:给审计留痕
如果把这些机制混成一团,实施时就会配置错:
- 以为开了 token 就足够安全
- 以为扫码就不需要追踪
- 以为 PIN 能替代所有后台权限控制
都不对。
最容易踩的 4 个坑
1)把 kiosk URL 当“安全登录页”
它只是公司范围入口。
2)手动选人却不开 PIN
这会显著放大代打卡风险。
3)在公共设备上保留后台登录态
官方源码已经在防这个坑。
4)关掉设备追踪后还期待有完整审计证据
少了一层留痕,就别指望事后百分百还原。
排错顺序
- 先确认 token 是否对应正确公司
- 再确认员工是否属于该公司
- 看入口是扫码还是手动选择
- 若手选失败,查公司是否要求 PIN、员工 PIN 是否匹配
- 最后查设备追踪和地理信息是否被禁用
最后一句话
Odoo 的 kiosk 设计重点不是“让页面公开”,而是“让公共终端可用但不失控”。token、PIN、条码和设备追踪各守一层边界,少配哪一层,风险就从哪一层漏出来。
DISCUSSION
评论区