不靠谱——SESSION_USER返回数据库连接用户而非真实业务用户,应改用数据库上下文变量(如PostgreSQL的current_setting)或显式传参方案。

SQL视图里用 SESSION_USER 做行过滤,靠谱吗?
不完全靠谱——SESSION_USER 返回的是数据库连接用户(比如 'app_user'),不是你应用里的真实登录人(比如 'zhangsan')。直接用它做权限判断,90% 的场景会失效。真正可用的是数据库上下文变量(如 PostgreSQL 的 current_setting('app.user_id'))或显式传入参数的视图(需配合应用层设置)。
PostgreSQL 视图中安全获取当前业务用户 ID 的方法
PostgreSQL 不支持在视图定义里直接读取 HTTP header 或 session 变量,必须靠应用层提前设置上下文:
- 应用在每次查询前执行:
SET app.user_id = '12345'; - 视图中用:
current_setting('app.user_id')::uuid(注意类型强转,否则报错) - 必须配
ALTER DATABASE ... SET app.user_id = 'dummy';或连接池启用session_preload_libraries,否则新连接看不到该变量 - 避免用
CURRENT_USER或SESSION_USER——它们返回的是postgres或app_user这类数据库账号,和业务用户无关
SQL Server 视图中怎么拿到真实用户?别碰 USER_NAME()
USER_NAME() 和 SUSER_SNAME() 都返回数据库登录名,不是应用用户。正确做法是用 SESSION_CONTEXT(N'user_id'):
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
- 应用层先执行:
EXEC sp_set_session_context @key=N'user_id', @value=N'abc123'; - 视图中写:
WHERE user_id = CAST(SESSION_CONTEXT(N'user_id') AS VARCHAR(50)) - 必须加
CAST或CONVERT,因为SESSION_CONTEXT返回SQL_VARIANT,直接比较会报错 - 不能依赖
ORIGINAL_LOGIN()——它返回的是最初登录名,中间经代理/连接池后就不可信
MySQL 视图没法用内置函数拿用户?那就别硬上
MySQL 8.0+ 没有等价于 SESSION_CONTEXT 或 current_setting 的安全机制。强行用 USER()、CURRENT_USER() 会暴露连接池账号,且无法区分真实操作人。此时应:
- 放弃“纯视图方案”,改用带参数的存储过程(
CREATE PROCEDURE report_for_user(IN p_user_id VARCHAR(36))) - 或在应用层拼接
WHERE user_id = ?,把过滤逻辑移出视图 - 若坚持用视图,只能接受“所有用户查同一份视图”,再靠 RLS(MySQL 8.0.22+ 支持行级安全策略)补位
- 千万别在视图里写
WHERE user_id = SUBSTRING_INDEX(USER(), '@', 1)——这是典型的安全幻觉,极易被绕过
最常被忽略的一点:视图本身不“执行”权限校验,它只是封装了 SQL。如果应用没提前设好上下文变量,或者类型转换漏了,视图会静默返回空结果或全表数据——既不报错,也不提醒,问题很难定位。










