一:安全对象是SQ L Server控制访问权限的资源,在SQL Server中的安全对象分为3个嵌套范围。


1、层次最高的是服务器范围。包含了登录名,数据库,端点。 

--1.管理服务器权限 use master go   if not exists(select name                from sys.server_principals               where name = 'ggg') begin 	create login [ggg]  	with password = 'ggg', 	     default_database = [master], 	     check_expiration = off, 	     check_policy = off  end   --授予修改跟踪权限 grant alter trace to ggg with grant option  --被授权者有将权限授予其他被授予者的权限   --创建windows登录名 create login [pc0627jvc\wcc] from windows with default_database = [master]   --授予创建数据库,查看数据库权限 grant create any database,       view any database to [pc0627jvc\wcc]  --拒绝关闭服务器权限 deny shutdown to [pc0627jvc\wcc]    --2.查询服务器权限 select p.name,  --授权者        s.name,  --被授权者                sp.class_desc,        sp.permission_name,        sp.state_desc     from sys.server_permissions  sp inner join sys.server_principals p         on p.principal_id =  sp.grantor_principal_id         inner join sys.server_principals s         on s.principal_id = sp.grantee_principal_id where s.name in ('pc0627jvc\wcc','ggg') 


2、其次是数据库范围,是包含在服务器范围内的,控制数据库用户,数据库角色,安全凭证,架构等安全对象。 

--1.管理数据库权限 if not exists(select name                from sys.server_principals               where name = 'xyz') begin 	create login [xyz]  	with password ='xyz', 	     default_database =[master], 	     check_expiration = off, 	     check_policy =off 	 end   --创建数据库 if not exists(select name               from sys.databases               where name = 'test') begin 	create database test end   use test go  --创建数据库用户 if not exists(select name               from sys.database_principals               where name = 'xyz') begin 	create user xyz for login xyz end   --给数据库用户授予修改任何程序集、修改任何证书的权限 grant alter any assembly,       alter any certificate to xyz  --拒绝修改数据库级别的ddl触发器的权限 deny alter any database ddl trigger to xyz  revoke connect from xyz   --新建登录,新建数据库用户,并授予权限 use AdventureWorks go  create login testuser  with password = 'testuser',      check_expiration = off,      check_policy = off       create user testuser from login testuser   grant select on humanresources.department to testuser  grant select on production.productphoto to testuser  grant exec on humanresources.uspUpdateEmployeeHireInfo to testuser  grant create assembly to testuser  grant select on schema::person to testuser  deny impersonate on user::dbo to testuser  deny select on humanresources.employee(birthdate) to testuser  grant select on schema::sales to testuser   --2.查询数据库权限 select dppp.name as grantor,       --授权者 	   dppp.type_desc as grantor_type,  --数据库用户对应的登录名类型         	   dpp.name as grantee,  --被授予权限者 	   dpp.type_desc as grantee_type,         	   dp.class_desc, 	   ISNULL(o.type_desc,'') object_type_desc,  --对象类型         	   case when dp.class_desc = 'schema' 				 then SCHEMA_NAME(dp.major_id)                   			when dp.class_desc = 'object_or_column' 				 then case when minor_id = 0 								then OBJECT_NAME(dp.major_id)                                  						   else (select OBJECT_NAME(object_id) + '.' + name 								 from sys.columns  								 where object_id = dp.major_id 									   and column_id = minor_id) 					  end 			else '' 	   end as object_name,   --对象名称         	   dp.permission_name,   --权限名称 	   dp.state_desc         --授予状态		              from sys.database_permissions dp inner join sys.database_principals dpp   --被授予者 		on dp.grantee_principal_id = dpp.principal_id inner join sys.database_principals dppp  --授予者 		on dp.grantor_principal_id = dppp.principal_id left join sys.objects o 	   on o.object_id = dp.major_id where dpp.name = 'testuser' 


3、最内层是架构范围,它控制安全对象(架构本身)以及架构中的对象(比如:表、视图、存储过程、函数)。

use test go  --1.架构的拥有者 --1.1创建架构,拥有者是db_owner角色 create schema wcc authorization db_owner   --1.2显示架构的拥有者:db_owner select s.name,       --架构名称        dp.name,      --架构拥有者                dp.type_desc, --拥有者类型        dp.is_fixed_role --是否固定数据库角色        from sys.schemas s inner join sys.database_principals dp         on s.principal_id = dp.principal_id where s.name = 'wcc'   --1.3改变架构的所有权 alter authorization on schema::wcc to wclogin   --1.4显示架构的拥有者:wclogin select s.name,       --架构名称        dp.name,      --架构拥有者                dp.type_desc, --拥有者类型        dp.is_fixed_role --是否固定数据库角色        from sys.schemas s inner join sys.database_principals dp         on s.principal_id = dp.principal_id where s.name = 'wcc'   --1.5在新建架构下,创建表 create table wcc.it 	(it char(13) not null primary key, 	 itcreate datetime not null default getdate() 	)   use master go  --2.用户的默认架构 --2.1创建登录名 create login wclogin with password = 'wclogin',      default_database = test,      check_policy = off,      check_expiration = off       go  use test go   --2.2创建数据库用户,默认架构是dbo create user wclogin for login wclogin go   --2.3用户wclogin的默认架构是wcc alter user wclogin with default_schema = wcc go   --2.4显示用户wclogin的默认架构 select name,                --数据库用户名        type_desc,        default_schema_name  --默认架构 from sys.database_principals where name = 'wclogin'    --3.对象所属的架构 --3.1表it所属的架构 select t.name, --对象名称               s.name  --对象所属架构名称        from sys.tables t inner join sys.schemas s         on t.schema_id = s.schema_id where t.name = 'it'   --3.2把wcc下的表it转移到架构dbo下 alter schema dbo transfer wcc.it   --3.3再次查看表it的架构 select t.name, --对象名称                s.name  --对象所属架构名称        from sys.tables t inner join sys.schemas s         on t.schema_id = s.schema_id where t.name = 'it'   --4.1删除架构wcc,必须先删除架构下所有的对象,或者把架构下所有的对象都转移到其他架构 drop schema wcc   --4.2修改数据库用户wclogin的默认架构 alter user wclogin with default_schema = dbo    use AdventureWorks go  --5.1新建数据库用户名wclogin create user wclogin for login wclogin   --3.2授予wclogin用户,架构person的所有权 grant take ownership on schema::Person to wclogin   --3.3虽然授予了take ownership权限,但是这个架构的拥有者没有变 select s.name,       --架构名称        dp.name,      --架构拥有者                dp.type_desc, --拥有者类型        dp.is_fixed_role --是否固定数据库角色        from sys.schemas s inner join sys.database_principals dp         on s.principal_id = dp.principal_id where s.name = 'person'    --6.管理对象的权限 grant alter,execute,select on schema::Production to wclogin with grant option   grant insert,update,delete on schema::production to wclogin   revoke alter,select on schema::production to wclogin cascade   grant delete,insert,select,update on humanresources.department to wclogin   deny alter on humanresources.department to wclogin   revoke insert,update,delete on humanresources.department  to wclogin   --创建角色 create role reportview  --给角色授予权限 grant execute,view definition on dbo.uspgetmanageremployees to reportview 

当前连接在安全对象上的权限

use test go  --1.检测当前连接的是否有安全对象的权限  select HAS_PERMS_BY_NAME(null,                   --安全对象名称                          null,                   --测试权限的安全对象的类名                          'VIEW SERVER STATE')   --要检查的权限名称   select HAS_PERMS_BY_NAME(DB_NAME(),   --安全对象名称                          'database',  --测试权限的安全对象的类名                          'alter')     --要检查的权限名称    /*=================================== 语法:  { EXEC | EXECUTE ] AS <context_specification> [;]  <context_specification>::= { LOGIN | USER } = 'name'     [ WITH { NO REVERT | COOKIE INTO @varbinary_variable } ]  | CALLER  =====================================*/ --模拟数据库用户wclogin,测试是否对当前数据库有任何的权限 EXECUTE AS user = 'wclogin' GO SELECT HAS_PERMS_BY_NAME(db_name(), 'DATABASE', 'ANY'); GO REVERT;   --是否对表有select的权限 select HAS_PERMS_BY_NAME(SCHEMA_NAME(t.schema_id) + '.' + t.name,                          'OBJECT',                          'select'),        t.* from sys.tables t   --是否对某个表的列有select的权限 select HAS_PERMS_BY_NAME('production.product',                          'object',                          'select',                          c.name,                          'column'),       c.* from sys.columns c where object_id = object_id('production.product')    --2.当前连接,对于某个安全对象,在这个安全对象类上,有多少权限 select * from sys.fn_my_permissions(null,        --安全对象的名称                            'server')    --要列出权限的安全对象类   select * from sys.fn_my_permissions('production',--安全对象的名称                            'schema')    --要列出权限的安全对象类    --3.改变安全对象的所有权 alter authorization on schema::production to wclogin  alter authorization on endpoint::端点名称 to wclogin    --4.sql登录名绑定到凭据,可以访问非SQL Server的资源 create credential account with identity = 'pc0627jvc\wcc',      secret = 'wcc'       --把一个凭据绑定到一个登录名上      alter login wclogin with credential = account   --查询凭据 select * from  sys.credentials where name = 'account'   --查询登录名是否绑定到凭据 select sp.name, --登录名        c.name   --凭据名 from sys.server_principals sp inner join sys.credentials c         on sp.credential_id = c.credential_id where sp.name = 'wclogin' 



二:权限允许主体在安全对象上执行操作。grant、deny、revoke命令可以用于所有的安全对象范围,用来控制主体到安全对象的访问。grant用于启用对安全对象的访问;deny用于限制访问,可以禁止主体对安全对象的访问权限;revoke可以回收主体对安全对象的访问权限。

 

sys.fn_builtin_permissions ( [ DEFAULT | NULL ]     | empty_string | '<securable_class>' } )  <securable_class> ::=        APPLICATION ROLE | ASSEMBLY | ASYMMETRIC KEY     | CERTIFICATE | CONTRACT | DATABASE | ENDPOINT | FULLTEXT CATALOG     | LOGIN | MESSAGE TYPE | OBJECT | REMOTE SERVICE BINDING | ROLE     | ROUTE | SCHEMA | SERVER | SERVICE | SYMMETRIC KEY | TYPE      | USER | XML SCHEMA COLLECTION

  

--显示整个服务器所有的权限的层次结构、覆盖结构 ;with temp   --显示每个有覆盖权限的权限,在同一权限类别中的覆盖层次,用\\来划分 as ( select class_desc,        permission_name,                covering_permission_name,                parent_class_desc,        parent_covering_permission_name,                cast('( '+class_desc + ' ){' + permission_name +'} \\  ' as varchar(6000)) as c,        1 as level         from sys.fn_builtin_permissions(default) r where --parent_class_desc = ''        covering_permission_name <> ''  union all  select t.class_desc,        t.permission_name,                r.covering_permission_name,                t.parent_class_desc,        t.parent_covering_permission_name,                       CAST('( ' + r.class_desc + ' ){ ' + r.permission_name + ' } \\ ' + c as varchar(6000)),        level + 1  from temp t inner join sys.fn_builtin_permissions(default) r         on t.class_desc = r.class_desc            and t.covering_permission_name = r.permission_name --where r.covering_permission_name <> ''  ),   t    --显示每个有覆盖权限的权限,在同一权限类别中的覆盖层次,求level最大的 as (  	select * 	from temp t 	where level =  	( 		select level 		from 		(     			 select class_desc, 			        permission_name, 					MAX(level) as level 			 from temp  			 group by class_desc, 			          permission_name 		)a 		where a.class_desc = t.class_desc 		      and a.permission_name = t.permission_name 	) ),   tt   --对已经显示的覆盖层次,进一步求出上层权限类别的级联层次,用--->>>来划分 as ( select class_desc,        permission_name,                parent_class_desc,        parent_covering_permission_name,                    cast(c as varchar(6000)) as c,                1 as level from t  union all  select tt.class_desc,        tt.permission_name,                r.parent_class_desc,        r.parent_covering_permission_name,                cast(r.c + ' --->>> '  + tt.c as varchar(6000)) as c ,        tt.level + 1 as level       from tt inner join ( 	            SELECT  class_desc, 	                    permission_name, 	        	                    parent_class_desc, 	                    parent_covering_permission_name, 	            	                    cast(c as varchar(6000)) as c 	            FROM t 	             	            UNION ALL 	             	            select class_desc, 	                   permission_name,      			     			         	        	       			   parent_class_desc,             	       			   parent_covering_permission_name, 	       			   CAST('( ' + class_desc + ' ){ ' + permission_name + ' }'AS VARCHAR(6000)) AS c  	 	            from sys.fn_builtin_permissions(default) 	            WHERE covering_permission_name ='' 	       ) r 	                on r.class_desc = tt.parent_class_desc            and r.permission_name = tt.parent_covering_permission_name              ),   ttt   --对于没有覆盖权限的权限,直接求上层权限类别的级联层次,用--->>>来划分 as ( select class_desc,        permission_name,                parent_class_desc,        parent_covering_permission_name,                    cast('( ' + class_desc + ' ){ ' + permission_name + ' } --->>> '  as varchar(6000)) as c,                1 as level from sys.fn_builtin_permissions(default)  where covering_permission_name = ''  union all  select ttt.class_desc,        ttt.permission_name,                r.parent_class_desc,        r.parent_covering_permission_name,                cast('( ' + r.class_desc + ' ){ ' + r.permission_name + ' } --->>> '  + ttt.c as varchar(6000)) as c ,        ttt.level + 1 as level       from ttt inner join sys.fn_builtin_permissions(default) r         on r.class_desc = ttt.parent_class_desc            and r.permission_name = ttt.parent_covering_permission_name       )  	select class_desc, 	       permission_name, 	       c                  --有覆盖权限的权限 	from  tt 	where level =  	( 		select level 		from 		(     			 select class_desc, 			        permission_name, 					MAX(level) as level 			 from tt  			 group by class_desc, 			          permission_name 		)a 		where a.class_desc = tt.class_desc 		      and a.permission_name = tt.permission_name 	) 	 	union all   	 	select class_desc, 	       permission_name, 	       c                --没有覆盖权限的权限 	from  ttt 	where level =  	( 		select level 		from 		(     			 select class_desc, 			        permission_name, 					MAX(level) as level 			 from ttt  			 group by class_desc, 			          permission_name 		)a 		where a.class_desc = ttt.class_desc 		      and a.permission_name = ttt.permission_name 	)	   order by 1