SQL Server 本機(jī) Web 服務(wù)的使用方案
摘要:獲得有關(guān)如何設(shè)置 SQL Server 以便在異類環(huán)境中進(jìn)行 Web 服務(wù)訪問的詳細(xì)討論,并且了解更多有關(guān) SQL Server 中 Web
服務(wù)的主要方案的信息。
下載相關(guān)的 WebServicePerlScript.exe 代碼示例。
簡介在 SQL Server 中,我們向數(shù)據(jù)庫引擎中添加了對本機(jī) XML Web 服務(wù)的支持。這一功能是圍繞眾所周知的標(biāo)準(zhǔn)(如 SOAP 1.2
、WSDL 1.1 和 HTTP)設(shè)計的。將解決方案建立在這些標(biāo)準(zhǔn)之上,可以在大多數(shù)企業(yè)都擁有的異類環(huán)境中支持互操作性和服務(wù)擴(kuò)張。
添加到 SQL Server 中的新的基礎(chǔ)結(jié)構(gòu)大大有利于直接向服務(wù)器外部公開 Web 服務(wù),這是因為將本機(jī) SOAP 堆棧內(nèi)置到數(shù)據(jù)庫
引擎中消除了使用中間層進(jìn)程(如 IIS)達(dá)到這一目標(biāo)的需要。它還使 SQL Server 能夠作為組件參與面向服務(wù)的體系結(jié)構(gòu),
因為服務(wù)在這些新的體系結(jié)構(gòu)中提供了黏合劑。本機(jī) XML Web 服務(wù)使您既可以將存儲過程作為 Web 服務(wù)公開,而且可以針對
數(shù)據(jù)庫服務(wù)器執(zhí)行特殊的 T-SQL 語句。實際上,我們已經(jīng)基于 SOAP 創(chuàng)建了一種新的訪問 SQL Server 的機(jī)制;SOAP 提供了
與當(dāng)前的 Tabular Data Stream (TDS) 專用二進(jìn)制協(xié)議幾乎相同的功能。
我們首先詳細(xì)考察如何設(shè)置 SQL Server 以便在異類環(huán)境中進(jìn)行 Web 服務(wù)訪問。我們將查看如何使用 Perl 腳本進(jìn)行數(shù)據(jù)庫
管理,并且簡要考察一下其他可以使用本機(jī) Web 服務(wù)的方案。
異類訪問請考慮這樣一個環(huán)境,在這里,運行在非 Microsoft 操作系統(tǒng)上的應(yīng)用程序需要連接到 SQL Server。對于此類應(yīng)用程序,
我們的建議是使用 SQL Server 授權(quán) (SQL-Auth) 連接到 SQL Server Web 服務(wù)。讓我們考察一下該機(jī)制是如何工作的。
要公開 Web 服務(wù),用戶需要做的第一件事情是創(chuàng)建一個終結(jié)點。請觀察如下所示的用于創(chuàng)建終結(jié)點的數(shù)據(jù)定義語言 (DDL)
語句。它將一個名為“GetCustomerInfo”的存儲過程公開為 Web 服務(wù)。
注 盡管術(shù)語 WEBMETHOD 在概念上與 ASP.NET 中的 [WebMethod] 相同,但它在其他方面與 ASP.NET 無關(guān)。
CREATE ENDPOINT sql_auth_endpoint STATE = STARTED AS HTTP( SITE = '*', PATH = '/sql/sql_auth', AUTHENTICATION = (BASIC), PORTS=(SSL) ) FOR SOAP( WEBMETHOD'GetCustomerInfo' ( name='AdventureWorks.dbo.GetCustomerInfo', schema=STANDARD ) , LOGIN_TYPE = MIXED, WSDL = DEFAULT, DATABASE = 'AdventureWorks', BATCHES=ENABLED, NAMESPACE = 'http://Adventure-Works/Customers/' ) 為了保持 SQL Server 中的“設(shè)計安全”主題,我們在任何情況下都不允許對 SQL Server 進(jìn)行 ANONYMOUS 訪問。這意味
著所有連接都需要使用受支持的身份驗證方案之一在 HTTP 傳輸級別進(jìn)行身份驗證。BASIC 是最常見和使用最廣泛的身份驗
證模型之一,因為它受到大多數(shù)客戶端的支持。但是,它也是最不安全的選擇,因為它要求以明文發(fā)送密碼。為了避免該問題,
我們要求每當(dāng)選擇 BASIC 作為身份驗證類型時,都要為 SSL 啟用終結(jié)點。要啟用 SSL,必須執(zhí)行以下命令:
httpcfg set ssl /i IP:Port /h Hash /g Guid; 其中,Hash 是證書哈希,Guid 是一個標(biāo)識注冊該證書的實體的全局唯一標(biāo)識符 (GUID) 字符串。用戶可以通過在 Certificate
中查找 Thumbprint 值來獲取證書的哈希值。作為最佳實施策略,請為 SQL Server 的每個實例創(chuàng)建單個 GUID,并且對于該實
例執(zhí)行的所有證書注冊,都使用同一個 GUID。您可以使用任何工具來發(fā)現(xiàn)該 GUID 值。Httpcfg.exe 隨附了 Windows 支持工具。
因此,在該示例中,它將成為:
httpcfg set ssl /i 1.1.1.1:443 /h 4463b7899c499a38812a7bbe7d73f4d31d026b2f /g '{2bb50d9c-7f6a-4d6f-873d-5aee7fb43290}' 其中,1.1.1.1 會被宿主 SQL Server 的計算機(jī)的 IP 地址替換。
那么,如何在終結(jié)點上啟用 SQL-Auth 呢?這是通過在終結(jié)點語法的 payload 節(jié)中指定“LOGIN_TYPE=MIXED”完成的。通
過指定“MIXED”,您可以使用集成式或 SQL 身份驗證對 SQL Server 實例進(jìn)行身份驗證。現(xiàn)在,我們使 SQL 憑據(jù)能夠作
為有效負(fù)載(消息)的一部分流動。在完成該工作時,我們已經(jīng)小心地確保傳輸憑據(jù)的 SOAP 標(biāo)頭與 WS-Security Username
標(biāo)記相匹配。遵循 WS-Security 標(biāo)準(zhǔn)自然可以提高互操作性;例如,只需很少的幾行代碼,就可以使用 Web Services
Enhancements 2.0 for Microsoft .NET (WSE) 生成用戶名標(biāo)記 SOAP 標(biāo)頭。
正如您可以在上述討論中看到的那樣,存在兩種級別的身份驗證:
傳輸級別
消息級別
現(xiàn)在,讓我們深入探討這兩個級別的身份驗證是如何工作的。
所有請求總是在傳輸級別進(jìn)行身份驗證。因此,如果用戶提交無效的 BASIC 身份驗證憑據(jù),則連接失敗,并且發(fā)生
HTTP 401 訪問被拒絕錯誤。如果用戶成功地在傳輸級別進(jìn)行身份驗證,則我們具有兩個選擇。我們可以使用傳輸憑
據(jù)或作為 SOAP 消息的一部分到來的憑據(jù)登錄 SQL Server。所選的憑據(jù)是由 SOAP 消息中是否存在 SQL-Auth 憑
據(jù)確定的。如果 SOAP 消息中存在憑據(jù),則我們將試圖使用 SQL-Auth 憑據(jù)登錄 SQL Server 數(shù)據(jù)庫。如果該方法
失敗,則我們向用戶返回失敗,并且我們不會后退到使用 BASIC 身份驗證憑據(jù)。如果 SOAP 消息中不存在憑據(jù),則
我們將試圖使用傳輸憑據(jù)登錄 SQL Server。
包含 SQL 憑據(jù)的 SOAP 消息如下所示:
<?xml version='1.0' encoding='utf-8'?>:<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>:<soap:Header>:<Security xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-wssecurity-secext-1.0.xsd'xmlns='http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'>:<wsse:UsernameToken>:<wsse:Username>user</wsse:Username>:<wsse:Password Type='http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-username-token-profile- 1.0#PasswordText'>:password </wsse:Password>:</wsse:UsernameToken>:</Security>:</soap:Header>:<soap:Body>:<GetCustomerInfoxmlns='http://Adventure-Works/Customers/'>:<CustomerID>1</CustomerID>:<OutputParam>Hello World</OutputParam>:</GetCustomerInfo>:</soap:Body>:</soap:Envelope>:
在 SOAP 消息中指定無效的憑據(jù)會產(chǎn)生以下 SOAP 錯誤(該錯誤被返回給用戶):
<?xml version='1.0' encoding='utf-8'?>:<SOAP-ENV:Envelope xml:space='preserve' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'xmlns:SOAP- ENV='http://schemas.xmlsoap.org/soap/envelope/'xmlns:sql='http://schemas.microsoft.com/sqlserver/2004/SOAP' xmlns:sqlsoaptypes='http://schemas.microsoft.com/sqlserver/2004/SOAP/types' xmlns:sqlrowcount='http://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlRowCount' xmlns:sqlmessage='http://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlMessage' xmlns:sqlresultstream='http://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlResultStream' xmlns:sqltransaction='http://schemas.microsoft.com/sqlserver/2004/SOAP/types/SqlTransaction' xmlns:sqltypes='http://schemas.microsoft.com/sqlserver/2004/sqltypes'>:<SOAP-ENV:Body>:<SOAP-ENV:Fault xmlns:sqlsoapfaultcode='http://schemas.microsoft.com/sqlserver/2004/SOAP/SqlSoapFaultCode'>:<faultcode>SOAP-ENV:Client</faultcode>:<faultstring>:There was an error in the incoming SOAPrequest packet: Client, LoginFailure, AccessDenied </faultstring>:<faultactor>http://schemas.microsoft.com/sqlserver/2004/SOAP</faultactor>:<detail xmlns:SOAP-1_2-ENV='http://www.w3.org/2003/05/soap-envelope'>:<SOAP-1_2-ENV:Code>:<SOAP-1_2-ENV:Value>SOAP-1_2-ENV:Sender</SOAP-1_2-ENV:Value>:<SOAP-1_2-ENV:Subcode>:<SOAP-1_2-ENV:Value>sqlsoapfaultcode:LoginFailure</SOAP-1_2-ENV:Value>:<SOAP-1_2-ENV:Subcode>:<SOAP-1_2-ENV:Value>sqlsoapfaultcode:AccessDenied</SOAP-1_2-ENV:Value>:</SOAP-1_2-ENV:Subcode>:</SOAP-1_2-ENV:Subcode>:</SOAP-1_2-ENV:Code>:<SOAP-1_2-ENV:Reason>:<SOAP-1_2-ENV:Text xml:lang='en-US'>:There was an error in the incoming SOAPrequest packet: Sender, LoginFailure, AccessDenied </SOAP-1_2-ENV:Text>:</SOAP-1_2-ENV:Reason>:<SOAP-1_2-ENV:Node>https://srikr-800.redmond.corp.microsoft.com:443/sql/sql_auth</SOAP-1_2-ENV:Node>:<SOAP-1_2-ENV:Role>:http://schemas.microsoft.com/sqlserver/2004/SOAP </SOAP-1_2-ENV:Role>:<SOAP-1_2-ENV:Detail />:</detail>:</SOAP-ENV:Fault>:</SOAP-ENV:Body>:</SOAP-ENV:Envelope>:
該解決方案只利用 HTTP、SOAP、BASIC 身份驗證和 SSL,這使它對于異類環(huán)境很理想。在下一部分中,我們將看到如何利
用該解決方案來創(chuàng)建 Perl 腳本,以便直接連接到 SQL Server。
使用 Perl 腳本進(jìn)行管理和監(jiān)視通過 SQL Server 中的 Web 服務(wù),可以從任何具有 Web 服務(wù)支持的平臺連接到 SQL Server。為了說明這一互操作性
,我們將創(chuàng)建 Perl 腳本以連接到 SQL Server。Perl 被普遍用于創(chuàng)建腳本,以便幫助管理和監(jiān)視數(shù)據(jù)庫服務(wù)器。
下面的示例說明了如何創(chuàng)建 Perl 腳本以監(jiān)視數(shù)據(jù)庫的狀態(tài)。SQL Server 已經(jīng)引入了對動態(tài)管理視圖的支持,這些
視圖提供了有關(guān)正在運行的服務(wù)器的動態(tài)狀態(tài)信息。在該示例中,我們創(chuàng)建了一個 Perl 腳本,以便通過查詢名為
dm_exec_connections 的動態(tài)視圖來監(jiān)視與數(shù)據(jù)庫之間的活動連接的數(shù)量。
我們假設(shè)運行這段代碼的計算機(jī)已經(jīng)正確安裝和配置了 Perl。
這里的示例使用 ActiveState 5.8.x Perl 軟件包。該腳本利用下列軟件包:
安裝 http://theoryx5.uwinnipeg.ca/ppms/Crypt-SSLeay.ppd
安裝 http://theoryx5.uwinnipeg.ca/ppms/XML-Parser.ppd
安裝 http://theoryx5.uwinnipeg.ca/ppms/libxml-perl.ppd
安裝 http://theoryx5.uwinnipeg.ca/ppms/XML-RegExp.ppd
安裝 http://theoryx5.uwinnipeg.ca/ppms/XML-DOM.ppd
在該示例中,我們需要 SSL,因為 Perl 應(yīng)用程序?qū)⑹褂?BASIC 身份驗證和 SQL-Auth,并且 XML 軟件包需要分析
響應(yīng)并顯示結(jié)果。
注 有關(guān)完整腳本的信息,請參見相關(guān)的下載。
下面的代碼塊將 SOAP Lite 軟件包實例化。我們需要明確要求將輸出格式化為 XML,以便可以分析響應(yīng)。
my $soap = SOAP::Lite ->:uri('http://Adventure-Works/Customers/') ->:proxy('https://srikr-800/sql/sql_auth') ->:outputxml(1):
接下來,我們需要為該連接設(shè)置憑據(jù)。因為我們打算使用 SQL-Auth,所以我們需要按如下方式初始化 UsernameToken 標(biāo)頭。
# sample Yukon security SOAPheader # <wsse:Security xmlns:wsse='http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'>:# <wsse:UsernameToken>:# <wsse:Username>sql_user</wsse:Username>:# <wsse:Password Type='http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-username-token-profile-1.0#PasswordText'>:foo-bar1 </wsse:Password>:# </wsse:UsernameToken>:# </wsse:Security>:my $Username = SOAP::Data->name('Username' => 'AdminUser'); my $Password = SOAP::Data->name('Password' => 'password') ->attr({Type =>:'http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-username-token-profile-1.0#PasswordText'}):my $UsernameToken= SOAP::Data->name('UsernameToken') ->value(SOAP::Data->value($Username, $Password)):my $security = SOAP::Header->name(Security) ->attr({'xmlns' =>:'http://docs.oasis-open.org/wss /2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'}) ->value($UsernameToken):
BASIC 身份驗證憑據(jù)是通過實現(xiàn)以下存根傳入的:
sub SOAP::Transport::HTTP::Client::get_basic_credentials { return 'User' => 'Password':} 注 建議不要在腳本文件中存儲/引用密碼。用戶在處理密碼時應(yīng)該遵循標(biāo)準(zhǔn)的安全準(zhǔn)則。
接下來,我們調(diào)用 Web 方法。因為我們將執(zhí)行 T-SQL 批處理語句,所以代碼如下所示:
# # Invoking a sqlbatch to retrieve the number of connections $soap ->:on_action (sub { return '''';}):$method = SOAP::Data->name('sqlbatch')->attr({xmlns =>:'http://schemas.microsoft.com/sqlserver/2004/SOAP'}):@param = ( SOAP::Data->name(BatchCommands =>:'select session_id, net_transport, protocol_type from sys.dm_exec_connections')):
最后,我們分析 XML 響應(yīng)以檢索數(shù)據(jù):
for my $node($doc->getElementsByTagName('row')) { print 'n':for my $kid ($node->getChildNodes) { print $kid->getNodeName():print ':: ':for my $gkid ($kid->getChildNodes) { print $gkid->getNodeValue():#print the actual values for the columns } print 't':} print 'n':} 運行該 Perl 腳本可以生成以下輸出:
Testing SOAP::Lite client against AdventureWorks Contacts sample web service. Calling sqlbatch Server response... Server response... session_id:: 54 net_transport:: HTTP protocol_type:: SOAP connection_id::5EC2B4E2-39A6-4FA7-BBDB-144DAED59A41 session_id:: 53 net_transport:: Shared memory protocol_type:: TSQL connection_id:: 5AE50B7D-D919-4FBC-BA42-6069A12F4D30 session_id:: 53 net_transport:: Session protocol_type:: TSQL connection_id::05830BE9-F12F-429D-BBAC-E4EEB2C528EF parent_connection_id:: 5AE50B7D-D919-4FBC-BA42-6069A12F4D30 上述輸出表明與 SQL Server 之間存在兩個連接:一個連接使用二進(jìn)制協(xié)議 TDS,并且顯示為 protocol_type:: TSQL;
另一個連接對應(yīng)于在運行該 Perl 腳本時生成的 SOAP/HTTP 連接。
我希望將您的注意力引到 session_id 列上面。該會話標(biāo)識符和與該請求關(guān)聯(lián)的數(shù)據(jù)庫引擎中的 spid(會話進(jìn)程標(biāo)識符)匹配。
有兩個條目的 spid 等于 53,因為一個對應(yīng)于物理連接(net_transport 是共享內(nèi)存),另一個對應(yīng)于在同一物理連接上進(jìn)行
的邏輯會話。(有關(guān)多個活動結(jié)果集的詳細(xì)信息,請參閱 Multiple Active Result Sets (MARS) in SQLServer 2。)該邏
輯會話的 parent_connection_id 與物理連接匹配這一事實證明了這一點。對于 TDS 而言,連接和會話緊密聯(lián)系在一起;換
句話說,用戶無法從不同的物理連接加入現(xiàn)有的會話。SOAP 訪問使用戶能夠通過在請求中指定適當(dāng)?shù)臅挊?biāo)頭來加入現(xiàn)有會話。
在 SOAP 中使用多個會話這一主題需要專門撰文加以闡述。感興趣的讀者可以閱讀 SQL Server Books Online 來獲得有關(guān)如
何啟用和使用會話的詳細(xì)信息。
其他方案現(xiàn)在,讓我們考察其他一些方案。大多數(shù)數(shù)據(jù)庫應(yīng)用程序都在存儲過程中內(nèi)置了大量以數(shù)據(jù)為中心的邏輯。本機(jī) XML Web 服務(wù)
通過使得將存儲過程公開為 Web 服務(wù)變得非常容易來利用這一投資。另外,本機(jī) Web 服務(wù)還可以提高性能,因為數(shù)據(jù)訪問是在
進(jìn)程內(nèi)發(fā)生的,而不是被發(fā)送到中間層進(jìn)程。
查找服務(wù)
當(dāng) SQL Server 宿主數(shù)據(jù)以供引用/查找時,可以使用 Web 服務(wù)作為公開該數(shù)據(jù)的理想機(jī)制。在該方案中,數(shù)據(jù)庫充當(dāng)大量數(shù)據(jù)
的儲存庫。Web 服務(wù)利用數(shù)據(jù)庫引擎查詢處理功能來獲取結(jié)果。此類查詢中的結(jié)果集定義良好,并且大約為幾個 KB。此類方案的示例包括:
產(chǎn)品目錄
向用戶返回特定于地區(qū)的信息(天氣、交通)的具有位置意識的 Web 服務(wù)。
用于 Intranet 的雇員目錄
報告生成服務(wù)
在很多方案中,數(shù)據(jù)庫服務(wù)器宿主作為報告基礎(chǔ)的數(shù)據(jù)。在 Intranet 內(nèi)部,將這些報告公開為 Web 服務(wù)是很方便的。用戶可
以輕松地創(chuàng)建 T-SQL 存儲過程,以便使用 SQL Server 中的 Web 服務(wù)生成和公開報告。您還可以輕松地將 Web 服務(wù)的結(jié)果嵌
入到 Office 應(yīng)用程序(如 Excel 和 InfoPath)中。這不僅使客戶端應(yīng)用程序可以更加容易地檢索數(shù)據(jù),而且還免除了數(shù)
據(jù)庫管理員的支持附加基礎(chǔ)結(jié)構(gòu)以便公開 Web 服務(wù)的負(fù)擔(dān)。用戶還能夠使用本機(jī) Web 服務(wù)的批處理訪問功能來運行特殊查詢和生成報告。
跨平臺訪問用戶定義的類型
SQL Server 引入了對用戶定義類型的支持。借助于用戶定義的類型 (UDT),您可以擴(kuò)展數(shù)據(jù)庫的標(biāo)量類型系統(tǒng)(不僅僅是為系
統(tǒng)類型定義您自己的別名 — 該功能在以前版本的 SQL Server 中已經(jīng)可用)。例如,您可以定義一個名為 Point 的 UDT 類型,
以捕獲點的 x 和 y 坐標(biāo)。本機(jī) Web 服務(wù)利用了公共語言運行庫中提供的序列化框架,并且啟用了諸如 XML 之類類型的傳輸。
然后,客戶端平臺可以將該 XML 反序列化為在其平臺上定義的對象。這就使 Java 客戶端能夠發(fā)送和接收 UDT 實例。
移動方案
現(xiàn)在,任何能夠分析 XML 和提交 HTTP 請求的設(shè)備都可以訪問 SQL Server。有了這一前提,再加上在丟棄連接時重新加入現(xiàn)
有會話的能力,非常適合于為移動設(shè)備和不定時連接的設(shè)備開發(fā)應(yīng)用程序,而這又使得隨時、隨地訪問 SQL Server 成為可能。
異步服務(wù)
可以將本機(jī) Web 服務(wù)與 SQL Service Broker(也通過 SQL Server 提供)結(jié)合使用,以便構(gòu)建提供異步服務(wù)的解決方案。請
考慮一個訂單處理工作流。您可以公開一個 SQL Server Web 服務(wù),該服務(wù)接收訂單,并且通過立即確認(rèn)它已經(jīng)收到了該訂單進(jìn)
行響應(yīng)。然后,可以將該訂單輸入到服務(wù)代理程序隊列中,以便進(jìn)行處理。訂單的履行可能需要調(diào)用其他 Web 服務(wù)。在履行該訂
單時,我們可以使用客戶端已經(jīng)預(yù)訂的任何通知機(jī)制來通知該客戶端。
小結(jié)本機(jī) XML Web 服務(wù)利用了您在數(shù)據(jù)庫服務(wù)器方面的投資,并且使您的數(shù)據(jù)庫能夠作為服務(wù)提供程序參與工作。我已經(jīng)詳細(xì)說明了
如何使用該功能提供對異類環(huán)境中 SQL Server 中宿主的數(shù)據(jù)的訪問,并且描述了其他適合本機(jī) Web 服務(wù)的方案。本機(jī) XML Web
服務(wù)通過使范圍更為廣泛的客戶端能夠連接到 SQL Server,提高了互操作性,促進(jìn)了服務(wù)的擴(kuò)張。
