这既是预期的行为,也是记录在案的行为。你所经历的就是所谓的所有权链。
当一个物体,如
VIEW
或
PROCEDURE
,如果
USER
他们也有权使用该对象
隐含地
授予对对象引用的任何对象的访问权限,这些对象与该对象具有相同的所有者,同时处于该对象的范围内。在这种情况下,你有一个
用户
谁创造了一个
视图
哪一个
SELECT
s来自具有相同所有者的其他对象(推测
dbo
或者别的什么),所以即使
用户
没有对底层表的显式访问权限
视图
允许他们隐式许可。
虽然我很感激您为我们提供了一些细节,但我将使用对象DDL设置我自己的示例。首先,让我们创建一个测试数据库
用户
CREATE DATABASE YourDB;
GO
USE YourDB;
GO
CREATE USER SomeUser WITHOUT LOGIN; --Example User
GO
CREATE SCHEMA SomeSchema; --Example schema
GO
GRANT CONTROL ON SCHEMA::SomeSchema TO SomeUser;
GRANT CREATE TABLE TO SomeUser;
GRANT CREATE VIEW TO SomeUser;
GRANT SELECT ON SCHEMA::SomeSchema TO SomeUser;
所以
用户
有创建权限
视图
s和
TABLE
s、 他们
CONTROL
“他们的”模式,他们也可以
选择
从他们的模式。
现在让我们创建一些示例对象:
CREATE TABLE dbo.SomeTable (SomeID int);
CREATE TABLE dbo.AnotherTable (AnotherID int);
--We don't need any sample data, this is just permissions checking;
GO
GRANT SELECT ON dbo.SomeTable TO SomeUser;
注:我同意
用户
明确访问
SomeTable
,但不是
AnotherTable
.
现在,作为
用户
,我要
CREATE
一些
视图
s、 然后做一些测试
选择
s
EXECUTE AS USER = 'SomeUser';
GO
SELECT SomeID
FROM dbo.SomeTable; --Works
GO
CREATE VIEW SomeSchema.SomeView AS
SELECT SomeID AS ID
FROM dbo.SomeTable;
GO
SELECT ID
FROM SomeSchema.SomeView; --Works
GO
SELECT AnotherID
FROM dbo.AnotherTable; --Doesn't work.
GO
CREATE VIEW SomeSchema.AnotherView AS
SELECT AnotherID AS ID
FROM dbo.AnotherTable;
GO
SELECT ID
FROM SomeSchema.AnotherView; --Works, due to permission chaining
GO
GO
REVERT; --back to normal
正如我们所看到的,这正如我所期望的那样
选择
反对
SomeSchema.AnotherView
使用以下命令工作并返回数据集
dbo.AnotherTable
以及
选择
直接对着物体
dbo。另一张桌子
失败,错误为:
对象“AnotherTable”、数据库“YourDB”、架构“dbo”的SELECT权限被拒绝。
为了解决这个问题,正如我提到的,更改模式的所有者
用户
正在使用:
--Let's change the owner of the schema
ALTER AUTHORIZATION ON SCHEMA::SomeSchema TO SomeUser;
现在我们可以再次测试,只需查询2
视图
s
--Now let's try those VIEWs again
EXECUTE AS USER = 'SomeUser';
GO
SELECT SomeID
FROM dbo.SomeTable; --Works, we have explicit SELECT on the table
GO
SELECT ID
FROM SomeSchema.AnotherView; --Doesn't work, we don't have explicit permission and ownership chaining fails
GO
REVERT;
这次查询针对
某种模式。另一种观点
也
失败,与我们尝试查询时遇到的权限错误相同
dbo。另一张桌子
直接。
清理
:
USE master;
GO
ALTER DATABASE YourDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
DROP DATABASE YourDB;