在您回答“使用 current_user()”(这在许多情况下确实有效)或“使用 user()”(实际上不起作用)之前,请阅读以下内容...
我正在尝试在表上创建一个视图,该视图限制用户对表中某些行的访问,由用户连接的 IP 地址控制。
我的第一次尝试是这样的:
create table testtable (
`RowID` bigint not null auto_increment,
`owner` varchar(64),
`key` varchar(64),
`val` varchar(64),
primary key (`RowID`)
);
create view testview (
`RowID`,
`owner`,
`key`,
`val`
) as select
`testtable`.`RowID` as `RowID`,
`testtable`.`owner` as `owner`,
`testtable`.`key` as `key`,
`testtable`.`val` as `val`
from testtable
where (testtable.owner = substring_index(current_user(), '@', -1));
create user 'testuser'@'192.168.3.30' identified by 'testpass';
grant select, insert, update, delete on testview to 'testuser'@'192.168.3.30';
现在的理论是,我应该能够从主机 192.168.3.30 以 testuser 身份登录并执行类似的操作select * from testview
并获得适用于我的 testtable 的正确子集。
以上不起作用。它不起作用的原因是默认情况下current_user()
返回视图的定义器,导致没有数据,或者(更糟)错误的数据,这取决于定义器是谁。如果我想current_user()
返回调用用户,我需要创建一个带有SQL SECURITY INVOKER
子句的视图,这也限制了调用用户的安全权限,从而违背了代码的初衷。
我很想使用user()
,但不幸的是,它几乎总是返回主机名/域而不是 IP 地址。
旁注,以防不清楚:在这种情况下,在 PHP(或 Ruby、perl 或其他任何东西)中获取 IP 地址是没有用的。我正在设置一些数据库安全性,因此依赖客户端显然是不够的。我需要 SQL 中的 IP 地址。
对于寻找想法/参考/背景的好奇:
作为参考,我从这里得到了这个漂亮的安全技巧的想法,但他们使用的是用户名而不是 IP 地址,这会使这更容易。就我而言,我正在尝试建立一个主机数据库,该数据库是从主机本身部分更新的。我不想为每台主机设置不同的用户,但我确实希望每台主机能够更新自己的记录(文件系统、风扇速度、温度等)。