SQL Server 本機 Web 服務的使用方案
Srik Raghavan
Microsoft Corporation
適用于:
SQL Server
Web 服務
摘要: 獲得有關如何設置 SQL Server 以便在異類環(huán)境中進行 Web 服務訪問的詳細討論,并且了解更多有關 SQL Server 中 Web 服務的主要方案的信息。
下載相關的 WebServicePerlScript.exe 代碼示例。

本頁內(nèi)容
![]() |
簡介 |
![]() |
異類訪問 |
![]() |
使用 Perl 腳本進行管理和監(jiān)視 |
![]() |
其他方案 |
![]() |
小結(jié) |
簡介
在 SQL Server 中,我們向數(shù)據(jù)庫引擎中添加了對本機 XML Web 服務的支持。這一功能是圍繞眾所周知的標準(如 SOAP 1.2、WSDL 1.1 和 HTTP)設計的。將解決方案建立在這些標準之上,可以在大多數(shù)企業(yè)都擁有的異類環(huán)境中支持互操作性和服務擴張。
添加到 SQL Server 中的新的基礎結(jié)構(gòu)大大有利于直接向服務器外部公開 Web 服務,這是因為將本機 SOAP 堆棧內(nèi)置到數(shù)據(jù)庫引擎中消除了使用中間層進程(如 IIS)達到這一目標的需要。它還使 SQL Server 能夠作為組件參與面向服務的體系結(jié)構(gòu),因為服務在這些新的體系結(jié)構(gòu)中提供了黏合劑。本機 XML Web 服務使您既可以將存儲過程作為 Web 服務公開,而且可以針對數(shù)據(jù)庫服務器執(zhí)行特殊的 T-SQL 語句。實際上,我們已經(jīng)基于 SOAP 創(chuàng)建了一種新的訪問 SQL Server 的機制;SOAP 提供了與當前的 Tabular Data Stream (TDS) 專用二進制協(xié)議幾乎相同的功能。
我們首先詳細考察如何設置 SQL Server 以便在異類環(huán)境中進行 Web 服務訪問。我們將查看如何使用 Perl 腳本進行數(shù)據(jù)庫管理,并且簡要考察一下其他可以使用本機 Web 服務的方案。
異類訪問
請考慮這樣一個環(huán)境,在這里,運行在非 Microsoft 操作系統(tǒng)上的應用程序需要連接到 SQL Server。對于此類應用程序,我們的建議是使用 SQL Server 授權(quán) (SQL-Auth) 連接到 SQL Server Web 服務。讓我們考察一下該機制是如何工作的。
要公開 Web 服務,用戶需要做的第一件事情是創(chuàng)建一個終結(jié)點。請觀察如下所示的用于創(chuàng)建終結(jié)點的數(shù)據(jù)定義語言 (DDL) 語句。它將一個名為“GetCustomerInfo”的存儲過程公開為 Web 服務。
注 盡管術語 WEBMETHOD 在概念上與 ASP.NET 中的 [WebMethod] 相同,但它在其他方面與 ASP.NET 無關。
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 中的“設計安全”主題,我們在任何情況下都不允許對 SQL Server 進行 ANONYMOUS 訪問。這意味著所有連接都需要使用受支持的身份驗證方案之一在 HTTP 傳輸級別進行身份驗證。BASIC 是最常見和使用最廣泛的身份驗證模型之一,因為它受到大多數(shù)客戶端的支持。但是,它也是最不安全的選擇,因為它要求以明文發(fā)送密碼。為了避免該問題,我們要求每當選擇 BASIC 作為身份驗證類型時,都要為 SSL 啟用終結(jié)點。要啟用 SSL,必須執(zhí)行以下命令:
httpcfg set ssl /i IP:Port /h Hash /g Guid
其中,Hash 是證書哈希,Guid 是一個標識注冊該證書的實體的全局唯一標識符 (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 的計算機的 IP 地址替換。
那么,如何在終結(jié)點上啟用 SQL-Auth 呢?這是通過在終結(jié)點語法的 payload 節(jié)中指定“LOGIN_TYPE=MIXED”完成的。通過指定“MIXED”,您可以使用集成式或 SQL 身份驗證對 SQL Server 實例進行身份驗證。現(xiàn)在,我們使 SQL 憑據(jù)能夠作為有效負載(消息)的一部分流動。在完成該工作時,我們已經(jīng)小心地確保傳輸憑據(jù)的 SOAP 標頭與 WS-Security Username 標記相匹配。遵循 WS-Security 標準自然可以提高互操作性;例如,只需很少的幾行代碼,就可以使用 Web Services Enhancements 2.0 for Microsoft .NET (WSE) 生成用戶名標記 SOAP 標頭。
正如您可以在上述討論中看到的那樣,存在兩種級別的身份驗證:
? |
傳輸級別 |
? |
消息級別 |
現(xiàn)在,讓我們深入探討這兩個級別的身份驗證是如何工作的。
所有請求總是在傳輸級別進行身份驗證。因此,如果用戶提交無效的 BASIC 身份驗證憑據(jù),則連接失敗,并且發(fā)生 HTTP 401 訪問被拒絕錯誤。如果用戶成功地在傳輸級別進行身份驗證,則我們具有兩個選擇。我們可以使用傳輸憑據(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 腳本進行管理和監(jiān)視
通過 SQL Server 中的 Web 服務,可以從任何具有 Web 服務支持的平臺連接到 SQL Server。為了說明這一互操作性,我們將創(chuàng)建 Perl 腳本以連接到 SQL Server。Perl 被普遍用于創(chuàng)建腳本,以便幫助管理和監(jiān)視數(shù)據(jù)庫服務器。
下面的示例說明了如何創(chuàng)建 Perl 腳本以監(jiān)視數(shù)據(jù)庫的狀態(tài)。SQL Server 已經(jīng)引入了對動態(tài)管理視圖的支持,這些視圖提供了有關正在運行的服務器的動態(tài)狀態(tài)信息。在該示例中,我們創(chuàng)建了一個 Perl 腳本,以便通過查詢名為 dm_exec_connections 的動態(tài)視圖來監(jiān)視與數(shù)據(jù)庫之間的活動連接的數(shù)量。
我們假設運行這段代碼的計算機已經(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 應用程序?qū)⑹褂?BASIC 身份驗證和 SQL-Auth,并且 XML 軟件包需要分析響應并顯示結(jié)果。
注 有關完整腳本的信息,請參見相關的 下載 。
下面的代碼塊將 SOAP Lite 軟件包實例化。我們需要明確要求將輸出格式化為 XML,以便可以分析響應。
my $soap = SOAP::Lite -> uri('http://Adventure-Works/Customers/') -> proxy('https://srikr-800/sql/sql_auth') -> outputxml(1);
接下來,我們需要為該連接設置憑據(jù)。因為我們打算使用 SQL-Auth,所以我們需要按如下方式初始化 UsernameToken 標頭。
# 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'; }
注 建議不要在腳本文件中存儲/引用密碼。用戶在處理密碼時應該遵循標準的安全準則。
接下來,我們調(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 響應以檢索數(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 之間存在兩個連接:一個連接使用二進制協(xié)議 TDS,并且顯示為 protocol_type:: TSQL ;另一個連接對應于在運行該 Perl 腳本時生成的 SOAP/HTTP 連接。
我希望將您的注意力引到 session_id 列上面。該會話標識符和與該請求關聯(lián)的數(shù)據(jù)庫引擎中的 spid(會話進程標識符)匹配。有兩個條目的 spid 等于 53,因為一個對應于物理連接(net_transport 是共享內(nèi)存),另一個對應于在同一物理連接上進行的邏輯會話。(有關多個活動結(jié)果集的詳細信息,請參閱 Multiple Active Result Sets (MARS) in SQLServer 2 。)該邏輯會話的 parent_connection_id 與物理連接匹配這一事實證明了這一點。對于 TDS 而言,連接和會話緊密聯(lián)系在一起;換句話說,用戶無法從不同的物理連接加入現(xiàn)有的會話。SOAP 訪問使用戶能夠通過在請求中指定適當?shù)臅挊祟^來加入現(xiàn)有會話。在 SOAP 中使用多個會話這一主題需要專門撰文加以闡述。感興趣的讀者可以閱讀 SQL Server Books Online 來獲得有關如何啟用和使用會話的詳細信息。
其他方案
現(xiàn)在,讓我們考察其他一些方案。大多數(shù)數(shù)據(jù)庫應用程序都在存儲過程中內(nèi)置了大量以數(shù)據(jù)為中心的邏輯。本機 XML Web 服務通過使得將存儲過程公開為 Web 服務變得非常容易來利用這一投資。另外,本機 Web 服務還可以提高性能,因為數(shù)據(jù)訪問是在進程內(nèi)發(fā)生的,而不是被發(fā)送到中間層進程。
查找服務
當 SQL Server 宿主數(shù)據(jù)以供引用/查找時,可以使用 Web 服務作為公開該數(shù)據(jù)的理想機制。在該方案中,數(shù)據(jù)庫充當大量數(shù)據(jù)的儲存庫。Web 服務利用數(shù)據(jù)庫引擎查詢處理功能來獲取結(jié)果。此類查詢中的結(jié)果集定義良好,并且大約為幾個 KB。此類方案的示例包括:
? |
產(chǎn)品目錄 |
? |
向用戶返回特定于地區(qū)的信息(天氣、交通)的具有位置意識的 Web 服務。 |
? |
用于 Intranet 的雇員目錄 |
報告生成服務
在很多方案中,數(shù)據(jù)庫服務器宿主作為報告基礎的數(shù)據(jù)。在 Intranet 內(nèi)部,將這些報告公開為 Web 服務是很方便的。用戶可以輕松地創(chuàng)建 T-SQL 存儲過程,以便使用 SQL Server 中的 Web 服務生成和公開報告。您還可以輕松地將 Web 服務的結(jié)果嵌入到 Office 應用程序(如 Excel 和 InfoPath)中。這不僅使客戶端應用程序可以更加容易地檢索數(shù)據(jù),而且還免除了數(shù)據(jù)庫管理員的支持附加基礎結(jié)構(gòu)以便公開 Web 服務的負擔。用戶還能夠使用本機 Web 服務的批處理訪問功能來運行特殊查詢和生成報告。
跨平臺訪問用戶定義的類型
SQL Server 引入了對用戶定義類型的支持。借助于用戶定義的類型 (UDT),您可以擴展數(shù)據(jù)庫的標量類型系統(tǒng)(不僅僅是為系統(tǒng)類型定義您自己的別名 — 該功能在以前版本的 SQL Server 中已經(jīng)可用)。例如,您可以定義一個名為 Point 的 UDT 類型,以捕獲點的 x 和 y 坐標。本機 Web 服務利用了公共語言運行庫中提供的序列化框架,并且啟用了諸如 XML 之類類型的傳輸。然后,客戶端平臺可以將該 XML 反序列化為在其平臺上定義的對象。這就使 Java 客戶端能夠發(fā)送和接收 UDT 實例。
移動方案
現(xiàn)在,任何能夠分析 XML 和提交 HTTP 請求的設備都可以訪問 SQL Server。有了這一前提,再加上在丟棄連接時重新加入現(xiàn)有會話的能力,非常適合于為移動設備和不定時連接的設備開發(fā)應用程序,而這又使得隨時、隨地訪問 SQL Server 成為可能。
異步服務
可以將本機 Web 服務與 SQL Service Broker(也通過 SQL Server 提供)結(jié)合使用,以便構(gòu)建提供異步服務的解決方案。請考慮一個訂單處理工作流。您可以公開一個 SQL Server Web 服務,該服務接收訂單,并且通過立即確認它已經(jīng)收到了該訂單進行響應。然后,可以將該訂單輸入到服務代理程序隊列中,以便進行處理。訂單的履行可能需要調(diào)用其他 Web 服務。在履行該訂單時,我們可以使用客戶端已經(jīng)預訂的任何通知機制來通知該客戶端。
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
