SQL Server的Execute As与连接池结合使用的测试
簡(jiǎn)介
??? 在SQL Server中,Execute As關(guān)鍵字允許當(dāng)前賬戶在特定上下文中以另一個(gè)用戶或登錄名的身份執(zhí)行SQL語(yǔ)句,比如用戶張三有權(quán)限訪問(wèn)訂單表,用戶李四并沒有權(quán)限訪問(wèn)訂單表,那么給予用戶李四訪問(wèn)訂單的表的權(quán)限就有些過(guò)頭了,因?yàn)槔钏目赡苤挥性诤芴囟ǖ纳舷挛沫h(huán)境中才需要訪問(wèn)訂單表,因此可以在特定上下文中使用Execute As Login 張三,暫時(shí)以張三的身份訪問(wèn)訂單表,從而保證更安全的權(quán)限控制。
??? 另一方面,應(yīng)用程序通過(guò)網(wǎng)絡(luò)與數(shù)據(jù)庫(kù)連接是需要在傳輸層通過(guò)TCP協(xié)議,而TCP協(xié)議在建立連接的階段的成本會(huì)比較高(1.同步請(qǐng)求 2同步請(qǐng)求+Ack 3.確認(rèn) 這三個(gè)階段),因此減少TCP連接可以很大程度上提升性能。因此當(dāng)應(yīng)用程序與數(shù)據(jù)庫(kù)建立連接后,在一定空閑時(shí)間內(nèi)不在TCP協(xié)議上切斷連接,而是保持連接,連接的斷開操作僅僅是邏輯上斷開,當(dāng)新的請(qǐng)求由應(yīng)用程序發(fā)送到客戶端時(shí),復(fù)用之前建立在應(yīng)用程序與數(shù)據(jù)庫(kù)上的連接,從而極大的提升了連接性能。
??? 當(dāng)在連接池上使用Execute As切換連接的安全上下文時(shí)則可能產(chǎn)生的情況我們通過(guò)下述幾種實(shí)驗(yàn)來(lái)得出結(jié)論。
?
在使用連接池的情況下使用Execute As切換安全上下文
??? 試驗(yàn)中所用的連接字符串全部為:
1: data source=.;database=test;uid=GetMembers;pwd=sa;pooling=true;Connection Timeout=30 2:? 3:?實(shí)驗(yàn)一:使用動(dòng)態(tài)SQL,切換安全上下文
??? 該實(shí)驗(yàn)分別使用兩個(gè)連接,第一次連接中,用戶為GetMembers,將安全上下文切換為系統(tǒng)最大權(quán)限登錄名SA,連接斷開時(shí)保持SA安全上下文,應(yīng)用程序端發(fā)送的SQL代碼如代碼1:
1: EXECUTE AS LOGIN = 'sa';SELECT * FROM dbo.Higher;"?? 代碼1.第一次連接數(shù)據(jù)庫(kù)執(zhí)行的語(yǔ)句
?
??? 在將身份切換為SA后,正常查詢GetMembers沒有的dbo.Higher表的權(quán)限,執(zhí)行完代碼1所示的SQL后,連接正常關(guān)閉。第二次連接使用連接池復(fù)用第一次連接所建立的連接,執(zhí)行的SQL如代碼2:
1: SELECT * FROM Higher代碼2.第二次連接使用的SQL
???
??? 在Asp.net端看到的查詢結(jié)果如圖1所示。
???
??? 圖1.兩次連接在Asp.net中的信息
?
??? 由圖1可以看出,當(dāng)復(fù)用連接池時(shí),由于第一次連接以GetMembers登錄名登錄,安全上下文切換到SA并沒有切換回來(lái),第二次再次登錄時(shí)就會(huì)報(bào)錯(cuò),報(bào)的錯(cuò)對(duì)應(yīng)在SQL Server日志里如圖2所示。
??
??? 圖2.SQL Server端報(bào)錯(cuò)
?
??? 結(jié)論:由此看出,當(dāng)連接池復(fù)用時(shí),第一次連接切換了上下文第二次連接復(fù)用時(shí)就會(huì)直接報(bào)錯(cuò),這也是期待的結(jié)果,從而保證了安全性,如果希望采用這種方式結(jié)合連接池,則必須在第一次連接完使用Revert將安全上下文轉(zhuǎn)換回登錄時(shí)的安全上下文。
?
實(shí)驗(yàn)二:在存儲(chǔ)過(guò)程中使用Execute As轉(zhuǎn)換安全上下文
??? 還是兩次連續(xù)的連接,第一次在存儲(chǔ)過(guò)程中執(zhí)行Execute As轉(zhuǎn)換上下文為SA,代碼如代碼3所示:
1: CREATE PROCEDURE [dbo].[GetMembers] 2:? 3: AS 4:? 5: EXECUTE AS USER = 'sa'代碼3.在存儲(chǔ)過(guò)程中執(zhí)行Execute As
?
??? 第二次連接進(jìn)來(lái)的查詢執(zhí)行一個(gè)非常簡(jiǎn)單的Select語(yǔ)句,但沒有對(duì)應(yīng)權(quán)限,執(zhí)行結(jié)果如圖3所示:
圖3.第二次連接不會(huì)受第一次在存儲(chǔ)過(guò)程中改變上下文的影響
?
??? 在數(shù)據(jù)庫(kù)端對(duì)應(yīng)的跟蹤如圖4所示。
???
??? 圖4.對(duì)應(yīng)的跟蹤
?
??? 因此可以看出,在存儲(chǔ)過(guò)程中改變安全上下文對(duì)連接池?zé)o影響,安全上下文僅僅在存儲(chǔ)過(guò)程中有效。
?
實(shí)驗(yàn)三:連接池對(duì)隔離級(jí)別的影響
??? 在實(shí)驗(yàn)3中對(duì)連接的默認(rèn)隔離級(jí)別更改,更改為可序列化級(jí)別,SQL語(yǔ)句如代碼4所示。
1: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE代碼4.改變連接的隔離級(jí)別
?
??? 隨后的連接查詢并返回當(dāng)前連接的隔離級(jí)別,結(jié)果如圖5所示。
???
??? 圖5.改變隔離級(jí)別導(dǎo)致復(fù)用連接池中的連接隔離級(jí)別改變
?
??? 結(jié)論:使用連接池對(duì)修改Session級(jí)別的隔離級(jí)別用完必須改回默認(rèn)連接,否則可能導(dǎo)致后續(xù)連接在不正確的隔離級(jí)別下運(yùn)行。
?
實(shí)驗(yàn)四:在存儲(chǔ)過(guò)程中改變隔離級(jí)別的連接復(fù)用的影響
??? 下面我們?cè)诖鎯?chǔ)過(guò)程中改變隔離級(jí)別,代碼如代碼5所示:
1: create PROCEDURE [dbo].[TestIslation] 2: AS 3: SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 4:? 5: SELECT CASE transaction_isolation_level 6: WHEN 0 THEN 'Unspecified' 7: WHEN 1 THEN 'ReadUncommitted' 8: WHEN 2 THEN 'ReadCommitted' 9: WHEN 3 THEN 'Repeatable' 10: WHEN 4 THEN 'Serializable' 11: WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 12: FROM sys.dm_exec_sessions 13: where session_id = @@SPID代碼5.在存儲(chǔ)過(guò)程中更改隔離級(jí)別,并顯示當(dāng)前的隔離級(jí)別
?
??? 在隨后的連接中,在非存儲(chǔ)過(guò)程中調(diào)用顯示當(dāng)前Session隔離級(jí)別的語(yǔ)句,并打印,結(jié)果如圖6所示。
??? 圖6.
?
??? 由圖6可以看出,第三次連接在存儲(chǔ)過(guò)程內(nèi)改變隔離級(jí)別,第四次連接的隔離級(jí)別并不受影響。
?
?? 結(jié)論:在存儲(chǔ)過(guò)程內(nèi)改變隔離級(jí)別不會(huì)影響后續(xù)連接池的使用。
?
?
小結(jié)
??? 本文對(duì)在使用連接池情況下數(shù)據(jù)庫(kù)中的一些細(xì)節(jié)場(chǎng)景進(jìn)行了實(shí)驗(yàn),可以看到對(duì)于連接池復(fù)用來(lái)說(shuō),改變隔離級(jí)別可能會(huì)存在隱性的風(fēng)險(xiǎn),其他情況SQL Server都能夠顯式處理。因此使用連接池對(duì)修改Session級(jí)別的隔離級(jí)別用完必須改回默認(rèn)連接,或者在語(yǔ)句級(jí)別修改隔離等級(jí)而不是Session級(jí)別。
總結(jié)
以上是生活随笔為你收集整理的SQL Server的Execute As与连接池结合使用的测试的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ChatGPT太火!网易经营范围新增智能
- 下一篇: 转载:Redis 应用场景