我有2个模式,第一个模式中的一个对象需要访问另一个模式中的对象。例如:
CREATE VIEW I.ITest
AS
SELECT 1 as TestColumn
GO
CREATE VIEW O.OTest
AS
SELECT * FROM I.ITest
GO
EXEC ('SELECT * FROM O.OTest') AS USER = 'TestUser'
DROP VIEW O.OTest
DROP VIEW I.ITest
在上面的示例中,TestUser只能访问“O”架构。所以select本身工作正常,但因为视图正在从另一个模式'I'中进行选择,所以它失败并出现错误:
对象'ITest',数据库'MyDB',架构'I'拒绝了SELECT权限。
为了解决这个问题,我可以授予“O”架构访问“I”架构的权限,但这听起来不对,并且看起来绕过了架构权限。
可以做些什么?我做错了吗?什么是这种情况下的最佳做法?
由于
更新:我的架构由不同的数据库角色拥有,因此我通过简单地将两者的所有者更改为dbo,然后授予数据库角色访问架构的权限来解决此问题。这意味着所有者dbo可以看到所有内容,然后我可以仅为db角色授予特定权限,并且除非通过此模式,否则其他db对象不可用。谢谢你的帮助
答案 0 :(得分:1)
您应该在存储过程中的“其他”架构的视图中包装数据选择。然后授予存储过程的执行权限。虽然用户无法直接访问视图,但允许通过存储过程进行访问。
以下是演示安全原则的示例演练:
USE DATABASE SANDBOX;
--Create Logins
CREATE LOGIN UserOne WITH Password='Hello123';
CREATE LOGIN UserTwo WITH Password='Hello123';
--Create Database Users
CREATE USER UserOne;
CREATE USER UserTwo;
--Create the Test Schemas
CREATE SCHEMA SchemaOne AUTHORIZATION UserOne;
CREATE SCHEMA SchemaTwo AUTHORIZATION UserTwo;
--Create a View on SchemaOne
CREATE VIEW SchemaOne.ViewOne
AS SELECT 1 as TestColumn;
--Create a View on SchemaTwo
CREATE VIEW SchemaTwo.ViewTwo
AS SELECT * FROM SchemaOne.ViewOne;
--Test that the SchemaOne
EXEC('select * from SchemaOne.ViewOne') AS USER = 'UserOne'
--1
EXEC('select * from SchemaTwo.ViewTwo') AS USER = 'UserOne'
--The SELECT permission was denied on the object 'ViewTwo', database 'SANDBOX', schema 'SchemaTwo'.
--Create a stored procedure to safely expose the view within SchemaTwo to UserOne who's default Schema is
--SchemaOne.
CREATE PROCEDURE SchemaTwo.proc_SelectViewTwo
AS
select * from SchemaTwo.ViewTwo;
--Grant execute rights on the procedure
GRANT EXECUTE ON SchemaTwo.proc_SelectViewTwo TO UserOne;
--Test the
EXECUTE AS LOGIN='UserOne';
Exec SchemaTwo.proc_SelectViewTwo;
revert;
我的评论中提出的另一种方法是使用数据库角色来控制对多个模式的访问。使用上面解决方案中定义的主体,您可以使用数据库角色,如下所示:
EXEC sp_addrole 'CrossSchemaRole';
EXEC sp_addrolemember 'CrossSchemaRole','UserOne';
GRANT SELECT ON SCHEMA::SchemaOne TO CrossSchemaRole;
GRANT SELECT ON SCHEMA::SchemaTwo TO CrossSchemaRole;
EXECUTE AS LOGIN='UserOne';
select * from SchemaTwo.ViewTwo;
revert;
有人建议进一步阅读:
答案 1 :(得分:1)
当然,您授予用户权限而不是对象,就是这样。如果您或其他架构的所有者希望允许其他用户访问其中的对象(无论是表,视图还是其他对象),则由其他架构的所有者决定。仅仅因为您作为开发人员可以编写一个访问其他模式中的对象的过程,并不意味着任何运行您的过程的人都应该被允许这样做。角色是要走的路。