12. 查询数据库账号的所有权限

在SQL Server数据库中,登录账号分类如下:

(1) SQL账号,需要单独设置密码,比如:sa;

(2) Windows账号,登录windows的账号,比如: administrator,不需要另设密码;

(3) Windows Group 账号, 为本地用户组或域用户组,将组添加到登录,组成员不需要单独创建登录;

查看Windows账号,是否属于某一个/多个用户组:

exec xp_logininfo ‘windows_acount‘,‘ALL‘  --域用户格式为:domain_name\account_name

以下脚本,均假设最终登录账号为:test_login,所有数据库对应的user为test_user

. 有没有权限

1. 检查有没有登录权限

--是否存在有效的登录账号:是否被禁用,sql login还有:密码是否过期,是否被锁定
select is_disabled, loginproperty(name,‘Isexpired‘) is_expired, loginproperty(name,‘Islocked‘) is_locked, *
from sys.server_principals
where name = ‘test_login‘

2. 检查有没有访问某数据库的权限

USE DBA
GO

--检查是否有数据库的CONNECT权限即可
select b.* from sys.database_principals a
inner join sys.database_permissions b
on a.principal_id = b.grantee_principal_id
where SUSER_SNAME(a.sid) = ‘test_login‘
and b.permission_name = ‘CONNECT‘

--老的系统表sysusers也可以检查
SELECT name, hasdbaccess,* FROM sysusers a
WHERE SUSER_SNAME(a.sid) = ‘test_login‘

如果有很多个数据库,写个游标1个个去检查即可。

3. 检查有没有某个对象的权限

检查有没有某个对象的权限,一般是去尝试运行下脚本比较直观,如果去查各种权限表,角色错综复杂时,很难分辨;

SQL Server 2008之后引入了HAS_PERMS_BY_NAME这个函数,它可以检查当前账号的各种权限,检查其他用户需要用EXECUTE AS来切换:

USE DBA
GO
EXECUTE AS user = ‘test_user‘
GO
--对象权限
SELECT HAS_PERMS_BY_NAME(‘Sales.SalesPerson‘, ‘OBJECT‘, ‘INSERT‘);
SELECT HAS_PERMS_BY_NAME(‘sp_send_dbmail‘, ‘OBJECT‘, ‘EXEC‘);
--架构权限
SELECT HAS_PERMS_BY_NAME(‘test_schema‘, ‘SCHEMA‘, ‘SELECT‘);
REVERT;
GO

对于是否有登录、访问数据库的权限,用这个函数也可以判断:

USE master
GO
EXECUTE AS login = ‘test_login‘
GO
--登录权限,本机前2个参数为空即可
SELECT HAS_PERMS_BY_NAME(NULL, NULL, ‘CONNECT SQL‘);
REVERT;
GO

USE DBA
GO
EXECUTE AS user = ‘test_user‘
GO
--数据库权限
SELECT HAS_PERMS_BY_NAME(db_name(), ‘DATABASE‘, ‘CONNECT‘);
REVERT;

. 有哪些权限

权限可以直接分配给账号,也可以分配给账号所属的role,所以要把账号自身权限、所属role权限合并才是最终的账号权限。

Windows账号权限还可以通过用户组分配,所以还要检查这个Windows账号有没有属于某个用户组,如果有还需要加上这个用户组的权限;

下面的脚本,仅检查单个用户/用户组权限。

1. 实例级的权限

use master
GO
declare @svr_principal_name varchar(1024)
set @svr_principal_name = ‘test_login‘

declare @svr_principal_id int
select @svr_principal_id = principal_id
from sys.server_principals p
where p.name = @svr_principal_name

if OBJECT_ID(‘tempdb..#tmp_svr_role‘,‘U‘) is not null
    drop table #tmp_svr_role;
create table #tmp_svr_role
(
member_principal_id     int,
member_principal_name   varchar(512),
role_principal_id       int,
role_principal_name     varchar(512)
)

--获取登录账号的所有server role, 从sql server 2012开始,server role可以自定义,成员仅可为fixed server role
;with tmp
as
(
select * from sys.server_role_members
where member_principal_id = @svr_principal_id
union all
select rm.* from sys.server_role_members rm
inner join tmp
on rm.member_principal_id = tmp.role_principal_id
)
insert into #tmp_svr_role
select a.member_principal_id, b.name,
       a.role_principal_id, c.name
 from tmp a
inner join sys.server_principals b
on a.member_principal_id = b.principal_id
inner join sys.server_principals c
on a.role_principal_id = c.principal_id

--登录账号自身权限, sys.server_permissions不包含fixed server role权限,同时手动排除掉public权限
select a.principal_id as member_principal_id, a.name as member_principal_name,
       null as role_principal_id, null as role_principal_name,
       b.permission_name, b.state_desc
from sys.server_principals a
inner join sys.server_permissions b
on a.principal_id = b.grantee_principal_id
where a.principal_id = @svr_principal_id
and b.permission_name <> ‘CONNECT SQL‘
union all
--server role权限,包含fixed server role和自定义的server role
select a.member_principal_id, a.member_principal_name,
       a.role_principal_id, a.role_principal_name,
       isnull(b.permission_name,‘Fixed Server-Level Role: ‘+role_principal_name) as permission_name, isnull(b.state_desc,‘GRANT‘) as state_desc
from #tmp_svr_role a
left join sys.database_permissions b
on a.role_principal_id = b.grantee_principal_id
union all
--public server role权限,不可以取消public权限,它是每个登录账号的最小权限,仅可连接数据库实例
select @svr_principal_id as member_principal_id,@svr_principal_name as member_principal_name,
       principal_id as role_principal_id, name as role_principal_name,
       ‘CONNECT SQL‘ as permission_name, ‘GRANT‘ as state_desc
from sys.server_principals
where name = ‘public‘

Instance-Level Permissions

注意:服务器角色的权限可以做什么具体的事情,exec sp_srvrolepermission 有大致的介绍,但是也并没有全部列出每一种数据库操作,因为有些操作是被更高级的操作包含的。

2. 数据库级的权限

仅列出数据库级别的权限,具体的对象名称并没有列出。

use DBA
GO
declare @svr_principal_name varchar(1024)
set @svr_principal_name = ‘test_login‘

declare @db_principal_id    int,
        @db_principal_name  varchar(512)
select @db_principal_id = principal_id,
       @db_principal_name = name
from sys.database_principals p
where SUSER_SNAME(sid) = @svr_principal_name

if OBJECT_ID(‘tempdb..#tmp_db_role‘,‘U‘) is not null
    drop table #tmp_db_role;
create table #tmp_db_role
(
member_principal_id     int,
member_principal_name   varchar(512),
role_principal_id       int,
role_principal_name     varchar(512)
)

--获取登录账号在当前数据库的所有database role
;with tmp
as
(
select * from sys.database_role_members
where member_principal_id = @db_principal_id
union all
select rm.* from sys.database_role_members rm
inner join tmp
on rm.member_principal_id = tmp.role_principal_id
)
insert into #tmp_db_role
select a.member_principal_id, b.name,
       a.role_principal_id, c.name
 from tmp a
inner join sys.database_principals b
on a.member_principal_id = b.principal_id
inner join sys.database_principals c
on a.role_principal_id = c.principal_id

--登录账号在当前数据库的自身权限, sys.database_permissions不包含fixed database role权限,同时手动排除掉public权限
select a.principal_id as member_principal_id, a.name as member_principal_name,
       null as role_principal_id, null as role_principal_name,
       b.permission_name, b.state_desc
from sys.database_principals a
inner join sys.database_permissions b
on a.principal_id = b.grantee_principal_id
where a.principal_id = @db_principal_id
and b.permission_name <> ‘CONNECT‘
union all
--database role权限,包含fixed database role和自定义的database role
select a.member_principal_id, a.member_principal_name,
       a.role_principal_id, a.role_principal_name,
       isnull(b.permission_name,‘Fixed Database-Level Role: ‘+role_principal_name) as permission_name, isnull(b.state_desc,‘GRANT‘) as state_desc
from #tmp_db_role a
left join sys.database_permissions b
on a.role_principal_id = b.grantee_principal_id
union all
--public database role权限,不可以取消public权限,它是每个登录账号映射到当前数据库的最小权限,仅可连接当前数据库
select @db_principal_id as member_principal_id, @db_principal_name as member_principal_name,
       principal_id as role_principal_id, name as role_principal_name,
       ‘CONNECT‘ as permission_name, ‘GRANT‘ as state_desc
from sys.database_principals
where name = ‘public‘

Database-Level Permissions

注意:sysadmin的账号在数据库里可能并没有做映射,但权限是有的,隐式映射的用户是dbo

3. 对象级的权限

sys.database_permissions有很多对象类型,major_id, minor_id取决于class_desc,不同的对象关联不同的系统表/视图,脚本里仅列出了最常见的OBJECT_OR_COLUMN, SCHEMA对象权限。

--建立测试用的架构,对象,列
use DBA
GO
if object_id(‘test_grant‘,‘U‘) is not null
    drop table test_grant
GO
create table test_grant(c1 int, c2 int, c3 int)
grant select (c1, c2) on test_grant to test_user;

if object_id(‘test_schema.test_t1‘,‘U‘) is not null
    drop table test_schema.test_t1
GO
if exists(select 1 from sys.schemas where name  = ‘test_schema‘)
    drop schema test_schema
GO
create schema test_schema
create table test_schema.test_t1(c1 int, c2 int)
grant select on schema::test_schema to test_user;
GO

--开始获取对象权限
use DBA
GO
declare @svr_principal_name varchar(1024)
set @svr_principal_name = ‘test_login‘

declare @db_principal_id    int,
        @db_principal_name  varchar(512)
select @db_principal_id = principal_id,
       @db_principal_name = name
from sys.database_principals p
where SUSER_SNAME(sid) = @svr_principal_name

if OBJECT_ID(‘tempdb..#tmp_db_role‘,‘U‘) is not null
    drop table #tmp_db_role;
create table #tmp_db_role
(
member_principal_id     int,
member_principal_name   varchar(512),
role_principal_id       int,
role_principal_name     varchar(512)
)

--获取登录账号在当前数据库的所有database role
;with tmp
as
(
select * from sys.database_role_members
where member_principal_id = @db_principal_id
union all
select rm.* from sys.database_role_members rm
inner join tmp
on rm.member_principal_id = tmp.role_principal_id
)
insert into #tmp_db_role
select a.member_principal_id, b.name,
       a.role_principal_id, c.name
 from tmp a
inner join sys.database_principals b
on a.member_principal_id = b.principal_id
inner join sys.database_principals c
on a.role_principal_id = c.principal_id

--登录账号在当前数据库的自身对象权限(OBJECT_OR_COLUMN)
select a.principal_id as member_principal_id, a.name as member_principal_name,
       null as role_principal_id, null as role_principal_name,
       o.name as major_name, c.name as minor_name,
       b.permission_name, b.state_desc
from sys.database_principals a
inner join sys.database_permissions b
on a.principal_id = b.grantee_principal_id
left join sys.objects o
on b.major_id = o.object_id
left join sys.columns c
on (b.major_id = c.object_id and b.minor_id = c.column_id)
where a.principal_id = @db_principal_id
and b.class_desc = ‘OBJECT_OR_COLUMN‘
union all
--登录账号在当前数据库的自身对象权限(SCHEMA)
select a.principal_id as member_principal_id, a.name as member_principal_name,
       null as role_principal_id, null as role_principal_name,
       s.name as major_name, null as minor_name,
       b.permission_name, b.state_desc
from sys.database_principals a
inner join sys.database_permissions b
on a.principal_id = b.grantee_principal_id
left join sys.schemas s
on b.major_id = s.schema_id
where a.principal_id = @db_principal_id
and b.class_desc = ‘SCHEMA‘
union all
--database role的对象权限(OBJECT_OR_COLUMN)
select a.member_principal_id, a.member_principal_name,
       a.role_principal_id, a.role_principal_name,
       o.name as major_name, c.name as minor_name,
       b.permission_name, b.state_desc
from #tmp_db_role a
inner join sys.database_permissions b --inner join, 仅自定义的database role
on a.role_principal_id = b.grantee_principal_id
left join sys.objects o
on b.major_id = o.object_id
left join sys.columns c
on (b.major_id = c.object_id and b.minor_id = c.column_id)
where b.class_desc = ‘OBJECT_OR_COLUMN‘
union all
--database role的对象权限(SCHEMA)
select a.member_principal_id, a.member_principal_name,
       a.role_principal_id, a.role_principal_name,
       s.name as major_name, null as minor_name,
       b.permission_name, b.state_desc
from #tmp_db_role a
inner join sys.database_permissions b --inner join, 仅自定义的database role
on a.role_principal_id = b.grantee_principal_id
left join sys.schemas s
on b.major_id = s.schema_id
where b.class_desc = ‘SCHEMA‘
/*
union all
--public role有一些系统视图的select权限,可以忽略
select a.principal_id as member_principal_id, a.name as member_principal_name,
       null as role_principal_id, null as role_principal_name,
       o.name as major_name, c.name as minor_name,
       b.permission_name, b.state_desc
from sys.database_principals a
inner join sys.database_permissions b
on a.principal_id = b.grantee_principal_id
left join sys.all_objects o
on b.major_id = o.object_id
left join sys.all_columns c
on (b.major_id = c.object_id and b.minor_id = c.column_id)
where a.name = ‘public‘
*/

Object-Level Permissions

注意:如果对象的权限是通过role衍生的,而不是直接分配给user或者role,那么并不会被列出来。试想sysadmin 的角色,难道要列出所有数据库的所有对象吗?

. 查看自己的权限

1. 有没有登录权限

登录失败并不一定是没权限,还是找别人来检查自己账号的登录权限吧;

2. 有没有数据库访问权限

--列出所有可访问的数据库
SELECT *
FROM sys.databases
WHERE HAS_DBACCESS(name) = 1

3. 有没有对象访问权限

用上面提到HAS_PERMS_BY_NAME函数,它可以检查当前账号的各种权限;

SELECT HAS_PERMS_BY_NAME(‘test_sp‘, ‘Object‘ , ‘Execute‘)
SELECT HAS_PERMS_BY_NAME(‘test‘, ‘Database‘ , ‘Execute‘)

4. 有哪些权限

--实例级权限
SELECT * FROM fn_my_permissions(NULL, ‘SERVER‘);
--数据库级权限
SELECT * FROM fn_my_permissions (‘DBA‘, ‘DATABASE‘);
--对象权限,只能一个个对象检查,不能一次返回所有对象权限,和HAS_PERMS_BY_NAME类似
SELECT * FROM fn_my_permissions (‘test_grant‘, ‘OBJECT‘); 

用于检查自己权限的方法,同样也可以检查其他账号,用EXECUTE AS切换账号即可。

时间: 2024-08-14 02:31:18

12. 查询数据库账号的所有权限的相关文章

spring security使用hibernate进行查询数据库验证

前面查询数据库采用的都是jdbc方式,如果系统使用的是hibernate,该如何进行呢,下面就是实现步骤,关键还是实现自定义的UserDetailsService 项目结构如下: 使用hibernate,pom.xml文件如下: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLo

CentOS学习笔记--账号管理与权限配置

Linux 的账号管理与权限配置 管理员的工作中,相当重要的一环就是『管理账号』啦! 使用者标识符: UID 与 GID 虽然我们登陆 Linux 主机的时候,输入的是我们的账号,但是其实 Linux 主机并不会直接认识你的『账号名称』的,他仅认识 ID 啊 (ID 就是一组号码啦). 由于计算机仅认识 0 与 1,所以主机对于数字比较有概念的:至于账号只是为了让人们容易记忆而已. 而你的 ID 与账号的对应就在 /etc/passwd 当中哩.每个登陆的使用者至少都会取得两个 ID ,一个是使

SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统

1.前言本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管理系统实例. 使用技术:SpringBoot.mybatis.shiro.thymeleaf.pagehelper.Mapper插件.druid.dataTables.ztree.jQuery 开发工具:intellij idea 数据库:mysql.redis 2.表结构还是是用标准的5张表来展现权限.如下图:image 分别为用户表,角色表,资源表,用户角色表,角色资源表.在这个demo中使用了mybat

Linux MySQL8.0.12备份数据库

环境CentOS7.4 MySQL8.0.12 #备份地址 backupdir=/data/bak #备份文件后缀时间 time=_` date +%Y_%m_%d_%H_%M_%S ` #需要备份的数据库名称 db_name=friends #mysqldump命令使用绝对路径 /usr/local/mysql/bin/mysqldump $db_name | gzip > $backupdir/$db_name$time.sql.gz 同时修改MySQL的配置文件,my.cnf [mysql

JavaEE学习之Spring Security3.x——模拟数据库实现用户,权限,资源的管理

一.引言 因项目需要最近研究了下Spring Security3.x,并模拟数据库实现用户,权限,资源的管理. 二.准备 1.了解一些Spring MVC相关知识: 2.了解一些AOP相关知识: 3.了解Spring: 4.了解Maven,并安装. 三.实现步骤 本示例中使用的版本是Spring Security3.2.2.通过数据库实现Spring Security认证授权大致需要以下几个步骤: 1.新建maven web project(因为本示例使用的是maven来构建的),项目结构如下,

ORACLE查询数据库的锁表情况

  查询数据库的锁表情况语句如下: SELECT p.spid,a.serial#, c.object_name,b.session_id,b.oracle_username,b.os_user_name FROM v$process p,v$session a, v$locked_object b,all_objects c WHERE p.addr=a.paddr AND a.process=b.process AND c.object_id=b.object_id 如果表因为某些情况出现死

Java 通过JDBC查询数据库表结构(字段名称,类型,长度等)

Java 通过JDBC查询数据库表结构(字段名称,类型,长度等) 发布者:唛唛家的豆子 时间:2012-11-20 17:54:02 在JDBCPreparedStatement.executeQuery().getMetaData();后,我们可以通过ResultSetMetaData对象查询返回结果集的源数据信息,也就是表结构信息. 示例代码如下: package astar.sutil.db; import java.sql.Connection; import java.sql.Driv

Windows Phone本地数据库(SQLCE):11、使用LINQ查询数据库(翻译) (转)

这是“windows phone mango本地数据库(sqlce)”系列短片文章的第十一篇. 为了让你开始在Windows Phone Mango中使用数据库,这一系列短片文章将覆盖所有你需要知道的知识点.我将谈谈在windows phone mango本地数据库里怎么使用LINQ查询数据库. 1.数据库查询是什么 在windows phone上,语言集成查询(LINQ)被用作查询数据库.LINQ常用于表示对象和实际数据之间的连接.LINQ to SQL中的查询使用和LINQ 的查询相同的语法

SQL Server 2008数据库创建用户只读权限的两种方式

在SQL Server 2008中,为了保护数据库的安全,需要给不同的使用者开通不同的访问用户,那么如何简单的控制用户的权限呢?下面我们就创建一个只读用户,给大家学习使用. 一.命令行方式创建 新建查询窗口,然后输入以下命令然后执行即可 sqlserver命令方式增加登录名.用户名及赋予相应权限 sp_addlogin 'test','test','DB'  >>登录名.密码.登录的数据库 sp_grantdbaccess 'test'  >>将数据库用户加入到当前数据库 gran