經常有人來問我特定 SQL Server 資料庫裡的使用者無法刪除的問題,這問題其實跟 SQL Server 的安全性架構有很大關係,解決這個問題當然還是瞭解觀念的重要性大於知道如何解決問題。除了講解觀念外,本篇文章也會列出一些出問題時的情境,方便快速解決問題。

我先假設各位已經知道 驗證 (Authentication) 與 授權 (Authorization) 的差別,簡單的來說 驗證負責辨識登入者的身份,而授權在於提供特定特定身份授與特定的操作權限。

在 SQL Server 裡提供了兩種驗證模式,分別是 Windows 驗證 (Windows Authentication) 與 混合模式驗證 (Mixed Modes authentication),藉以控制應用程式連接 SQL Server 的方式。另外,SQL Server 又區分了兩種登入的類型,分別是 Windows 登入SQL Server 登入,在從應用程式連接資料庫時,使用 Windows 登入可以不用輸入密碼在連線參數上,這種登入方式是比較建議的登入方法。

在設定登入帳號時,該帳號可以隸屬於一個以上的 伺服器角色 (Server Role),這些在 SQL Server 中存在的伺服器角色數量是固定的,無法新增、也無法刪除,預設所有新增的「登入帳號」都會自動歸類在 public 這個伺服器角色下,這個 public 角色只有允許連接 SQL Server 的權力而已,並沒有任何資料庫的的存取權限。

所以我們從 SSMS ( Management Studio ) 中所看到的「安全性」節點,其實是為於「伺服器節點」之下,並不隸屬於任何資料庫,這是應用程式連接 SQL Server 時的第一個安全性關卡,應該妥為設定才行,不應該給予登入帳號有過大的權限,例如將該登入帳號加入到 sysadmin 伺服器角色之類的。

因此,這裡所儲存的是 登入帳號 (Login),而非 資料庫使用者 (Database User),這點非常重要。

當我們在任意一個資料庫中建立資料庫使用者時,所建立的其實是一個所謂的 安全性主體 (security principal),他代表的是一個能夠被賦予安全性設定的對象,也就是一個可授權的對象。

這裡的 資料庫使用者 在建立時必須對應到一個 登入帳戶,而在建立時可以設定任意的使用者名稱,方便好記即可(一般我們會習慣設定使用者名稱與登入名稱一致),並且挑選出一個登入帳戶,在設定好之後我們就可以針對這個 資料庫使用者 設定各種權限相關的設定,例如:資料庫角色、安全性實體、…等等。

如下圖是透過 SSMS 新增 資料庫使用者 的畫面,我看過許多人在建立資料庫使用者時,會勾選如下圖藍色框框的勾選項目,也就是設定該使用者「擁有特定的結構描述」,勾選這一項就會導致日後無法刪除資料庫使用者的問題,解決辦法在本文稍後會提及。

除了設定 SQL Server 預設的 資料庫角色 外,你也可以自行新增資料庫角色,並設定該角色應該有哪些權限能用,基於資安的最小權限原則 (Principle of least privilege),我們應該授與資料庫使用者最小的使用權限,以加強資料庫的存取安全性,這時我們就可以透過自訂的資料庫角色來設定適當的權限,最後再將資料庫使用者加入到該資料庫角色即可將權限套用完成。

若要設定 資料庫使用者資料庫角色 的細部權限,我們可以切換至 安全性實體 (Securables) 頁籤。所謂的 安全性實體 (Securable) 與 安全性主體 (Security Principle) 不太一樣,但中文卻被翻譯的非常相似,讀者必須特別小心。這裡的 安全性實體 (Securables) 指的是可以指派權限給特定 資料庫使用者資料庫角色 的資料庫物件。

在你搜尋出 安全性實體 (或 資料庫物件) 後,就可以針對這些物件設定更細部的權限,如下圖示,我選擇了一個預存程序,下方的權限部分就又分為 改變取得擁有權執行控制檢視定義 等權限,如果你只需給特定使用者「執行」的權限,就只要在「執行」權限的「授與」這一欄勾選即可。

接下來,在資料庫層級的安全性中,還有一個所謂的 結構描述 (Schema) 的觀念,這是從 SQL Server 2005 開始才有的概念,在 SQL Server 2000 以前,使用者名稱本身就是資料庫物件的一部分,但新的版本不再有這種限制,而改用 結構描述 (Schema) 來「擁有」這些資料庫物件。

如果由 結構描述 (Schema) 來「擁有」這些資料庫物件,那麼應該由誰來「擁有」結構描述 呢?當然是透過 資料庫使用者資料庫角色 囉!

第 1 種無法刪除的情境:資料庫預設 結構描述 (Schema) 的擁有者被指定了想刪除的資料庫使用者

也就是說,當有特定 結構描述 被特定 資料庫使用者 所擁有時,該 資料庫使用者 就會因為被鎖定導致無法刪除,所以在刪除資料庫使用者經常會遇到一個很常見的錯誤訊息如下:

Msg 15138, Level 16, State 1, Line 2
資料庫主體在資料庫中擁有 結構描述 且無法卸除。

那麼我們要怎樣才能一次瀏覽所有 結構描述 (Schema) 的擁有者是誰呢?以下這行 T-SQL 可以幫你列出

SELECT * FROM INFORMATION_SCHEMA.SCHEMATA

如果你發現你想刪除的資料庫使用者擁有了特定 結構描述 (Schema) 的話,你可以修改特定 結構描述 的擁有者給其他人,例如:dbo

移轉擁有權的 T-SQL 語法如下:

ALTER AUTHORIZATION ON SCHEMA::[db_owner] TO [dbo]

第 2 種無法刪除的情境:無法刪除多餘的 結構描述,所以也連帶無法刪除資料庫使用者

這問題並不常見,除非開發人員真的亂新增結構描述才會這樣,否則結構描述應該是在資料庫設計階段所設計過的,況且我們只要把該結構描述的擁有者改成其他資料庫使用者資料庫角色,就可以刪除該資料庫使用者了。

但如果因為設計有所改變而需要刪除特定結構描述卻無法刪除的話,其錯誤訊息如下:

訊息 3729,層級 16,狀態 1,行 2
無法 drop schema TESTUser,因為物件 'PK_Table_1' 正在參考它。

為了要刪除該結構描述,你必須要先轉移這些被參考到的資料庫物件的結構描述到另一個結構描述裡,以下是搜尋出所有該結構描述所用到的物件清單,這一行 T-SQL 指令可以幫你快速找出使用該結構描述的物件:(備註:如下範例請將 MySchema 修改成你的結構描述名稱

SELECT schema_name(uid) as SCHEMA_NAME, * FROM sysobjects
WHERE schema_name(uid) = 'MySchema'

假設我們要將 MySchema.View_1 物件轉移到 dbo 結構描述,其物件名稱會變成 dbo.View_1,那麼我們可以使用以下 T-SQL 執行轉移動作:

ALTER SCHEMA dbo TRANSFER MySchema.View_1

第 3 種無法刪除的情境:有資料庫角色的擁有者被指定了想刪除的資料庫使用者

這種問題的錯誤訊息如下:

Msg 15421, Level 16, State 1, Line 2
資料庫主體擁有資料庫角色且無法卸除。

一樣只要轉移擁有者即可,以下是方便查出所有資料庫角色擁有者的 T-SQL 語法:

SELECT user_name(owning_principal_id) as OWNER_NAME, * FROM [sys].[database_principals]

以下是轉移資料庫角色擁有者的語法:

ALTER AUTHORIZATION ON ROLE::[testrole] TO [dbo]

第 4 種無法刪除的情境:有 服務 的擁有者被指定了想刪除的資料庫使用者

這種問題的錯誤訊息如下:

Msg 15138, Level 16, State 1, Line 2
資料庫主體在資料庫中擁有 服務 且無法卸除。

以下是方便查出所有服務擁有者的 T-SQL 語法:

SELECT user_name(principal_id) as OWNER_NAME, * FROM [sys].[services]

結語

資料庫中還有許多其他物件都有可能因為參考到資料庫使用者而無法刪除,但熟悉了基本觀念後,應該就會懂得融會貫通,相信日後遇到無法刪除使用者的問題應該也能輕鬆的自行解決。

来源:http://blog.miniasp.com/post/2011/08/20/SQL-Server-Security-and-Unable-to-delete-database-user-problem.aspx

[转]SQL Server 安全性概論與無法刪除資料庫使用者的解決辦法的更多相关文章

  1. C# [Win32] [API] WS_TABSTOP 無效的解決辦法

    關鍵: IsDialogMessage function MSG msg; int bRet = 1; while (bRet != 0) { if (PeekMessageW(&msg, ( ...

  2. 如何將 MySQL 資料庫轉移到 Microsoft SQL Server 與 Azure SQL Database

    MySQL 是相當常用之資料庫伺服器,而微軟雲端服務 Microsoft Azure 上 Azure SQL Database 是一個功能強大且經濟實惠的選擇,透過本篇文章,使用 SQL Server ...

  3. SQL Server安全性专题一:简介

    原文:SQL Server安全性专题一:简介 一. 安全威胁与法则 1. 安全定义 2. 安全威胁 3. 安全法则 安全定义: 在SQLServer环境中,安全性可以认为是[数据保护].包括:  数 ...

  4. 第十三周翻译:SQL Server安全级别1:SQL Server安全性概述

    SQL Server安全级别1:SQL Server安全性概述 源自:Stairway to SQL Server Security Level 1: Overview of SQL Server S ...

  5. SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...

  6. SQL SERVER 安全性体系

    主体和安全实体 在 SQL Server 2008中,“主体”就是可以访问受保护资源且能获得访问资源所需权限的任何个人.组或流程.与旧版 SQL Server 一样,可以在 Windows 中定义主体 ...

  7. 如何查詢 SQL Server 資料庫中欄位值為 NULL 的資料(转)

    最近使用mssql的时候对于未null的字段查询不到 http://blogs.msdn.com/b/jchiou/archive/2008/05/01/sql-server-null.aspx 先建 ...

  8. 在 SQL Server 2012 附加 Adventure Works 範例資料庫

    原文地址:http://technet.microsoft.com/zh-tw/library/eb1f9417-4cca-4575-a725-187bcd60c7e7 附加数据库时报错 错误5123 ...

  9. [ Database ] [ Sybase ] [ SQLServer ] sybase 與SQL Server的界接方式

    目前我們有個專案Server A安裝了 SQL Server 2012,有個需求需要連線到另外一台Server B上的 Sybase 12.5的view, 先前試過了很多方法都無法連通.主要的原因是因 ...

随机推荐

  1. 【原创】MapReduce实战(一)

    应用场景: 用户每天会在网站上产生各种各样的行为,比如浏览网页,下单等,这种行为会被网站记录下来,形成用户行为日志,并存储在hdfs上.格式如下: 17:03:35.012ᄑpageviewᄑ{&qu ...

  2. php字符集转换

    PHP通过iconv将字符串从GBK转换为UTF8字符集. 1. iconv()介绍 iconv函数可以将一种已知的字符集文件转换成另一种已知的字符集文件.例如:从GB2312转换为UTF-8. ic ...

  3. 最新版PMBOK项目管理的五大过程组和十大知识领域

    PMBOK五大过程组是:启动过程.规划过程.执行过程.监控过程.收尾过程. 各用一句话概括项目管理知识体系五大过程组: 1.启动过程组:作用是设定项目目标,让项目团队有事可做: 2.规划过程组:作用是 ...

  4. 【转】js判断一个object对象是否为空

    判断一个对象是否为空对象,本文给出三种判断方法: 1.最常见的思路,for...in... 遍历属性,为真则为“非空数组”:否则为“空数组” for (var i in obj) { // 如果不为空 ...

  5. VC++ 崩溃处理以及打印调用堆栈

    title: VC++ 崩溃处理以及打印调用堆栈 tags: [VC++, 结构化异常处理, 崩溃日志记录] date: 2018-08-28 20:59:54 categories: windows ...

  6. Spring boot Jackson基本演绎法&devtools热部署

    1.针对POJO中的User类添加一些注解,使其某些数据不显示或者格式化某些数据类型,如下图: 2.启动Application,然后进入浏览器访问http://localhost:8080/user/ ...

  7. Sass初入门

    什么是CSS预处理器? CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行编码工作.   什 ...

  8. 使用SDL2出现 “error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main 中被引用” 时的可能错误记录

    这几天在使用SDL2,之前一直都没有错,直到上午把项目搬了个地方.结果一直出现 “error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main 中被引用” . 看了网 ...

  9. spring----面试题

    1.什么是Spring beans? Spring beans 是那些形成Spring应用的主干的java对象.它们被Spring IOC容器初始化,装配,和管理.这些beans通过容器中配置的元数据 ...

  10. js判断客户浏览器类型,版本

    在JS中判断浏览器的 类型,估计是每个编辑过页面的开发人员都遇到过的问题.在众多的浏览器产品中,IE.Firefox.Opera.Safari........众多品牌 却标准不一,因此时常需要根据不同 ...