MySQL仅提供数据库层访问控制,业务权限校验需结合其账户体系与应用代码实现:一、用用户权限做基础隔离;二、用视图隐藏敏感数据;三、在应用中动态过滤;四、用存储过程+DEFINER封装权限逻辑。

MySQL 本身不直接提供应用层的“权限校验”逻辑(比如判断用户能否访问某张订单),它负责的是数据库层面的访问控制——即谁(用户)能对哪些对象(库、表、列、存储过程等)执行什么操作(SELECT/INSERT/UPDATE/DELETE/EXECUTE 等)。真正的业务权限校验(如“普通员工不能看财务表”“张三只能查自己的订单”)需要结合 MySQL 的账户权限体系 + 应用代码逻辑来实现。
一、用 MySQL 用户权限做基础隔离
这是最底层、最安全的第一道防线。通过 CREATE USER 和 GRANT 控制谁连得上、能碰哪些数据。
- 创建专用应用账号,避免用 root 或高权限账号连接业务系统
- 按角色最小化授权:例如只给报表账号
SELECT权限,禁用写操作 - 限制访问来源:
CREATE USER 'app_read'@'192.168.10.%'比'app_read'@'%'更安全 - 及时回收权限:
REVOKE INSERT ON sales.orders FROM 'cashier'@'localhost';
二、用视图(VIEW)隐藏敏感字段或行级数据
视图可以封装查询逻辑,让不同角色看到“定制化”的数据切片,无需在应用里拼复杂 WHERE 条件。
- 为 HR 创建仅含姓名、部门、入职时间的员工视图,屏蔽薪资字段
- 为销售员创建只返回自己名下订单的视图:
CREATE VIEW my_orders AS SELECT * FROM orders WHERE salesperson_id = CURRENT_USER();(需配合应用传入用户名或使用代理用户) - 注意:视图不自动带权限,仍需给用户授予该视图的 SELECT 权限
三、在应用中做动态权限过滤(推荐主流做法)
MySQL 不支持行级策略(如 PostgreSQL 的 RLS),所以业务规则必须由应用控制。关键是在 SQL 查询中主动加入权限条件。
- 登录后从 session 或 token 中获取当前用户 ID、角色、所属部门等上下文
- 查询订单时,不是
SELECT * FROM orders,而是SELECT * FROM orders WHERE creator_id = ?或WHERE dept_id IN (SELECT dept_id FROM user_dept WHERE user_id = ?) - 把权限判断逻辑封装成 DAO 方法或中间件,避免每处 SQL 都手写 WHERE
- 敏感操作(如删除、导出)前,先查一次权限表或调用权限服务确认
四、用存储过程 + DEFINER 实现权限封装
适合需要复用且逻辑较固定的场景,比如“审批人只能审核本部门待办”。通过 DEFINER 让过程以高权限账号执行,但调用者只需有 EXECUTE 权限。
- 创建过程时指定
SQL SECURITY DEFINER,并用CURRENT_USER()或入参识别调用者身份 - 过程内部完成权限检查和数据过滤,对外只暴露简单接口
- 例:
CALL get_pending_approvals('zhangsan');内部自动关联部门、过滤状态、限制条数 - 注意:不要在过程里拼接用户输入,防止 SQL 注入;优先用参数化查询
不复杂但容易忽略:权限变更后记得 FLUSH PRIVILEGES;(仅修改 mysql 系统表时需要),而 GRANT/REVOKE 会自动刷新。真正健壮的权限体系,是数据库权限 + 应用层校验 + 审计日志三者结合的结果。










