為使用 ASP.NET 建立的 XML Web Service 設定安全性
要決定那個安全性實作最符合 XML Web Service,您需要考量兩個主要安全性原則:驗證和授權。驗證是根據憑證檢查識別的處理,例如透過使用者名稱和密碼檢查授權。只要識別通過驗證,授權會判斷識別是否獲得授權以存取資源。
使用 ASP.NET 建立的 XML Web Service 可透過 ASP.NET 提供的驗證和授權選項,或自訂以 SOAP 為基礎的安全性,來選擇其安全性選項。ASP.NET 與 Internet Information Server (IIS) 緊密配合,提供您數種驗證和授權選項。您也可以建立自訂驗證選項,例如使用 SOAP 標頭。此外,ASP.NET 也提供所謂的模擬功能,使用用戶端憑證來執行要求。如需使用模擬的詳細資訊,請參閱 ASP.NET 模擬。
這個主題中摘要了 ASP.NET 建置的 XML Web Service 所能使用的驗證和授權選項。如需 ASP.NET Web 應用程式可用安全性選項的詳細資訊,請參閱設定 ASP.NET Web 應用程式的安全性。
XML Web Service 的驗證選項
使用 ASP.NET 建立的 XML Web Service 有幾個驗證用戶端的選項可用,但問題在於該使用那個選項配合特定的 XML Web Service。要選擇正確的安全性選項,開發人員首先該決定安全性和效能層級。有些 XML Web Service 的用戶端憑證絕對要以加密方式才能透過網路傳送,這時就需要採用能將用戶端憑證加密的演算法。例如,開發人員撰寫處理信用卡的 XML Web Service 時,比起顧慮信用卡資訊加密耗用過多記憶體,會更擔心用戶端憑證是否會被竊取。
下列表格摘要了 ASP.NET建置之 XML Web Service 可用的驗證選項。前面加上 Windows 的選項屬於 Microsoft Windows 驗證選項,可供使用 ASP.NET 建立的 XML Web Service 使用。
驗證選項摘要
驗證選項 | 說明 |
---|---|
Windows - 基本 | 用於不安全的用戶端識別,使用者名稱和密碼是以 Base64 編碼的純文字字串傳送。這種驗證中的密碼和使用者名稱經過編碼,但未加密。居心不良的電腦使用者用網路監視工具就能攔截使用者名稱和密碼。 |
Windows - 基本透過 SSL | 用來在網際網路上保護用戶端識別安全。使用者名稱和密碼使用 Secure Sockets Layer (SSL) 而非純文字加密,透過網路傳送。這種方式設定容易,適用於網際網路,但使用 SSL 會降低效能。 |
Windows - 摘要式 | 用來在網際網路上保護用戶端識別安全。使用雜湊法將用戶端憑證以加密方式傳輸,使密碼不是以純文字傳輸。此外,摘要式驗證 可用於 Proxy 伺服器。但是其他平台並未普遍支援這種方式。 |
Windows - 整合式 Windows | 使用 NTLM 或 Kerberos。使用密碼編譯與使用者的 Microsoft Internet Explorer Web 瀏覽器進行交換。 |
Windows - 用戶端認證 | 用來在網際網路上保護用戶端識別安全。要求每個用戶端從共同信任的憑證授權處取得認證。認證會選擇性地對應至使用者帳號,供 IIS 授權存取 XML Web Service。 |
表單 | XML Web Service 不支援。這種系統是使用 HTTP 用戶端重新導向,把未驗證的要求重新導向至 HTML 表單。XML Web Service 多數的用戶端可能不想要使用 UI 提供憑證。您必須採用其他方法避免登入表單。 |
SOAP 標頭 - 自訂 | 適用於安全/非安全 Internet 案例。使用者憑證在 SOAP 訊息的 SOAP 標頭內傳遞。Web 伺服器的平台不管是否裝載 XML Web Service,都提供自訂驗證實作。 |
除了使用 SOAP 標頭,上列所有選項的安全性設定是以組態檔配合 IIS 來指定。如需組態檔的詳細資訊,請參閱 ASP.NET 組態。自訂 SOAP 標頭選項與驗證和授權有關,所以放在下面的<授權>章節為您說明。
Windows 驗證
IIS 和 ASP.NET 都使用 Windows 內建安全性來支援 Web 應用程式 (包括 XML Web Service) 的驗證作業。Windows 提供三個驗證選項:基本、摘要式和整合式 Windows,每個選項都可以搭配 SSL 使用。除了基本以外,由於所有的 Windows 驗證選項都使用某些形式來加密資料,因此 SSL 提供的進階加密通常只與基本或用戶端認證合用。
無論 Windows 使用哪種驗證選項,XML Web Service 和 XML Web Service 用戶端的設定方式都很類似。用戶端認證是例外,所以下列另外說明設定伺服器和用戶端以使用用戶端認證的步驟。不需要在 XML Web Service 中加入程式碼即可使用 Windows 驗證,因為驗證選項是在組態檔和 IIS 中設定。但是用來將用戶端憑證傳遞給 XML Web Service 的程式碼,就必須加入 XML Web Service 用戶端。
如果 XML Web Service 選擇 SSL 為驗證機制之一,您必須使用 IIS 來為裝載 XML Web Service 的 Web 應用程式或為 XML Web Service 本身設定 SSL。這樣服務描述和自服務描述產生的 Proxy 類別才會反映出 XML Web Service 使用 SSL (如果服務描述和服務說明網頁透過 SSL 存取)。而且,服務描述中連至 XML Web Service 的URL 前面會加上 http。如需設定 SSL 的詳細資訊,請參閱 IIS 文件。
若要針對 Windows 驗證設定 XML Web Service
透過 IIS,設定 XML Web Service 以使用 Windows 驗證。
IIS 可讓您指定目錄或檔案層級的安全性。如果您想針對每個檔案個別指定 XML Web Service 的安全性,請在 IIS中的 .asmx 檔案設定 XML Web Service 的許可。.asmx 檔案是 XML Web Service 的進入點 (Entry Point)。如需詳細資訊,請參閱 IIS 文件。
修改組態檔以指定 Windows 驗證。
到組態檔中,將 authentication XML 項目的 mode 屬性設定為 "Windows"。如需設定組態檔的詳細資訊,請參閱 ASP.NET 組態。下列程式碼範例為修改組態檔來使用 Windows 驗證。
// Fragment of a Web.config file. <authentication mode= "Windows"> </authentication>
使用 Windows 驗證將用戶端憑證傳遞給 XML Web Service
建立 Proxy 類別的新執行個體當作 XML Web Service。如果 Proxy 類別尚未產生,請參閱建立 XML Web Service Proxy取得詳細資訊。
建立 NetworkCredential 類別的新執行個體,設定 UserName、Password 和 Domain 屬性。
建立 CredentialCache 的新執行個體。
使用 CredentialCache 的 Add 方法,將 NetworkCredential 加入 CredentialCache。
將 CredentialCache 的執行個體指派給 Proxy 類別的 Credentials 屬性。
如果己使用整合式 Windows 驗證,您必須將 Credentials 屬性設定為 DefaultCredentials。
將 Credentials 屬性設定為 CredentialCache.DefaultCredentials 時,用戶端會依據伺服器的設定方式,與伺服器協調以進行 Kerberos 和 (或) NTLM 驗證。
下列程式碼範例使用 Windows 驗證,設定將用戶端憑證傳遞給 XML Web Service 方法。
Imports System Imports System.Web.Services.Protocols Imports System.Net Imports MyMath Public Class Calculator Public Shared Sub Main() ' Create a new instance of the proxy class to an ' XML Web service method. Dim mathproxy As MyMath.Math = New MyMath.Math() ' Create a new instance of CredentialCache. Dim mycredentialCache As CredentialCache = New CredentialCache() ' Create a new instance of NetworkCredential using the client ' credentials. Dim credentials As NetworkCredential = New _ NetworkCredential(UserName,SecurelyStoredPasword,Domain) ' Add the NetworkCredential to the CredentialCache. mycredentialCache.Add(New Uri(mathproxy.Url), "Basic", _ credentials) ' Add the CredentialCache to the proxy class credentials. mathproxy.Credentials = mycredentialCache ' Call the method on the proxy class. Dim result As Integer result = mathproxy.Add(3,5) End Sub End Class [C#] using System; using System.Web.Services.Protocols; using System.Net; using MyMath; public class Calculator { public static void Main() { // Create a new instance of the proxy class to an XML // Web service method. MyMath.Math math = new MyMath.Math(); // Create a new instance of CredentialCache. CredentialCache credentialCache = new CredentialCache(); // Create a new instance of NetworkCredential using the client // credentials. NetworkCredential credentials = new NetworkCredential(UserName,SecurelyStroredPassword,Domain); // Add the NetworkCredential to the CredentialCache. credentialCache.Add(new Uri(math.Url), "Basic", credentials); // Add the CredentialCache to the proxy class credentials. math.Credentials = credentialCache; // Call the method on the proxy class. int result = math.Add(3,5); } }
用戶端認證驗證
用戶端認證可提供您驗證的安全機制。用戶端接獲要求傳送電子文件時,會呼叫用戶端憑證,接著 SSL 會連接至 Web 伺服器來識別用戶端。SSL 連接會在網路上傳遞用戶端認證中的用戶端憑證之前,對該憑證加密。用戶端和 Web 伺服器間的通訊,是經過用戶端傳送的加密金鑰配合 Web 伺服器提供的金鑰,進行加密。一旦通訊建立後,只有用戶端 和伺服器電腦可使用 SSL 連接進行通訊。
用戶端認證可由認證授權處取得,可為 Web 伺服器本身,或是用戶端和伺服器間共同信任的媒介。一旦取得認證且 Web 伺服器也設定為可接受用戶端認證,那麼呼叫 XML Web Service 時,用戶端就能透過 SLL 連接將用戶端認證傳送給 Web 伺服器。如需用戶端認證的詳細資訊,請參閱 IIS 文件。
若要針對用戶端認證的驗證設定 XML Web Service
下列清單概觀介紹了設定 IIS 的方法,來驗證採用戶端認證的用戶端。如需詳細資訊,請參閱 IIS 文件。
安裝 SSL。
將 Web 應用程式設定為接受用戶端認證。
修改組態檔,以指定 XML Web Service 的 Windows 驗證。
到組態檔中,將 authentication XML 項目的 mode 屬性設定為 "Windows"。如需設定組態檔的詳細資訊,請參閱 ASP.NET 組態。下列程式碼範例為修改組態檔來使用 Windows 驗證。
// Fragment of a Web.config file. <authentication mode= "Windows"> </authentication>
使用 Windows 驗證將用戶端憑證傳遞給 XML Web Service
建立 Proxy 類別的新執行個體當作 XML Web Service。如果 Proxy 類別尚未產生,請參閱建立 XML Web Service Proxy取得詳細資訊。
建立 X509Certificate 的新執行個體。
叫用 CreateFromCertFile 方法從檔案載入用戶端認證。
用戶端可從信任的認證授權取得用戶端認證檔案。如需詳細資訊,請參閱 IIS 文件。
將 X509Certificate 加入 Proxy 類別的 ClientCertificates 集合。
下列程式碼範例示範 XML Web Service 用戶端如何使用用戶端認證來傳遞憑證。從 Web 伺服器發行的用戶端認證是從有 CreateFromCertFile 方法的檔案載入,接著加入 Proxy 類別的 ClientCertificates 屬性。
' Instantiate proxy class to a Bank XML Web service. Dim bank As BankSession = new BankSession() ' Load the client certificate from a file. Dim x509 As X509Certificate = X509Certificate.CreateFromCertFile("c:\user.cer") ' Add the client certificate to the ClientCertificates property ' of the proxy class. bank.ClientCertificates.Add(x509) ' Call the method on the proxy class, which requires authentication ' using client certificates. bank.Deposit(500) [C#] // Instantiate proxy class to a Bank XML Web service. BankSession bank = new BankSession(); // Load the client certificate from a file. X509Certificate x509 = X509Certificate.CreateFromCertFile(@"c:\user.cer"); // Add the client certificate to the ClientCertificates property // of the proxy class. bank.ClientCertificates.Add(x509); // Call the method on the proxy class, which requires // authentication using client certificates. bank.Deposit(500);
XML Web Service 的授權選項
授權的目的在於決定識別對既定的資源是否需授與要求的存取權限。將存取授權給指定資源的方法有兩種:檔案授權及 URL 授權。檔案授權的許可是在 IIS 中以每個檔案為基礎進行設定,所以不管有沒有 Windows 驗證都可以使用。URL 授權則可與 ASP.NET 支援的任何內建驗證方法合用。使用 URL 授權時,組態是透過組態檔完成。組態檔可選擇性地授與或拒絕使用者存取任何與 ASP.NET 有關的檔案,包括 .asmx 檔案。
如需以每個檔案為基礎設定授權的詳細資訊,請參閱 IIS 文件。
如需使用組態檔設定授權的詳細資訊,請參閱 ASP.NET 授權。
SOAP 標頭 - 自訂解決方案
用戶端認證等 Windows 驗證方法需要靠 HTTP 傳輸,但 SOAP 則是獨立傳輸。使用 ASP.NET 建構的 XML Web Service 用 SOAP 來取代 HTTP。所以,建立自訂驗證方法的另一個理由,是為了將驗證和交易作業拆開。若要這麼做,請在 SOAP 標頭內傳遞驗證憑證。
SOAP 標頭相當適合傳遞 Out-of-Band 或與 XML Web Service 的語意 (Semantics) 無關聯的資訊。相較之下,SOAP 訊息的 Body 項目包含 XML Web Service 方法的 in 和 out 參數,並經過 XML Web Service 方法處理。而 Header 項目是選擇性的,所以可由基礎架構處理,也就是由針對提供自訂驗證方法而開發的基礎架構來處理。
下列自訂解決方案使用 ASP.NET 來建構,以提供使用 SOAP 標頭的驗證方法。解決方案是以下列步驟建構而成:
- 建構自訂 HTTP Module,可在裝載 XML Web Service 的 Web 伺服器上執行。
- HTTP Module 剖析 HTTP 訊息,檢查是否為 SOAP 訊息。
- 如果 HTTP Module 偵測到 SOAP 訊息,便會讀取 SOAP 標頭。
- 如果 SOAP 訊息的 SOAP 標頭具有驗證憑證,HTTP Module 會引發自訂 global.asax 事件。
若要修改 XML Web Service 以使用自訂 SOAP 標頭驗證,XML Web Service 必須進行兩項工作:指定服務本身預期包含驗證憑證的 SOAP 標頭,並且授權用戶端存取 XML Web Service。本文提供的範例中, HTTP Module 的功能是驗證使用者並設定 Context 屬性,供 XML Web Service 判斷用戶端是否獲得授權可存取 XML Web Service。
接著,XML Web Service 用戶端將預期的 SOAP 標頭加入 SOAP 要求,以服務用戶端本身的用戶端憑證填入這個要求,藉此將本身的的憑證傳送給 XML Web Service。有一點相當重要,這個範例中的文字是以可讀取的文字在網路上傳送,也就是沒有經過加密。若您覺得純文字不足以保護應用程式安全,請加上加密演算法。
下列程式碼範例的 HTTP Module 能夠剖析 SOAP 要求的 HTTP 訊息。如果 HTTP 訊息為 SOAP 訊息,便會發生自訂 WebServiceAuthenticationEvent
。
using System;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.Web.Services.Protocols;
namespace Microsoft.WebServices.Security {
public sealed class WebServiceAuthenticationModule : IHttpModule
{
private WebServiceAuthenticationEventHandler
_eventHandler = null;
public event WebServiceAuthenticationEventHandler Authenticate
{
add { _eventHandler += value;}
remove {_eventHandler -= value;}
}
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.AuthenticateRequest += new
EventHandler(this.OnEnter);
}
private void OnAuthenticate(WebServiceAuthenticationEvent e)
{
if (_eventHandler == null)
return;
_eventHandler(this, e);
if (e.User != null)
e.Context.User = e.Principal;
}
public string ModuleName
{
get{ return "WebServiceAuthentication"; }
}
void OnEnter(Object source, EventArgs eventArgs) {
HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
Stream HttpStream = context.Request.InputStream;
// Save the current position of stream.
long posStream = HttpStream.Position;
// If the request contains an HTTP_SOAPACTION
// header, look at this message.
if (context.Request.ServerVariables["HTTP_SOAPACTION"] == null)
return;
// Load the body of the HTTP message
// into an XML document.
XmlDocument dom = new XmlDocument();
string soapUser;
string soapPassword;
try
{
dom.Load(HttpStream);
// Reset the stream position.
HttpStream.Position = posStream;
// Bind to the Authentication header.
soapUser =
dom.GetElementsByTagName("User").Item(0).InnerText;
soapPassword =
dom.GetElementsByTagName("Password").Item(0).InnerText;
}
catch (Exception e)
{
// Reset the position of stream.
HttpStream.Position = posStream;
// Throw a SOAP exception.
XmlQualifiedName name = new
XmlQualifiedName("Load");
SoapException soapException = new SoapException(
"Unable to read SOAP request", name, e);
throw soapException;
}
// Raise the custom global.asax event.
OnAuthenticate(new WebServiceAuthenticationEvent (context, soapUser, soapPassword));
return;
}
}
}
下列程式碼範例為 HTTP Module 收到 SOAP 要求時引發的自訂驗證事件。
namespace Microsoft.WebServices.Security {
using System;
using System.Web;
using System.Security.Principal;
public class WebServiceAuthenticationEvent : EventArgs {
private Iprincipal _IPrincipalUser;
private HttpContext _Context;
private string _User;
private string _Password;
public WebServiceAuthenticationEvent(HttpContext context)
{
_Context = context;
}
public WebServiceAuthenticationEvent(HttpContext context,
string user, string password)
{
_Context = context;
_User = user;
_Password = password;
}
public HttpContext Context
{
get { return _Context;}
}
public IPrincipal Principal
{
get { return _IPrincipalUser;}
set { _IPrincipalUser = value;}
}
public void Authenticate()
{
GenericIdentity i = new GenericIdentity(User);
this.Principal = new GenericPrincipal(i, new String[0]);
}
public void Authenticate(string[] roles)
{
GenericIdentity i = new GenericIdentity(User);
this.Principal = new GenericPrincipal(i, roles);
}
public string User
{
get { return _User; }
set { _User = value; }
}
public string Password
{
get { return _Password; }
set { _Password = value; }
}
public bool HasCredentials {
get
{
if ((_User == null) || (_Password == null))
return false;
return true;
}
}
}
}
下列程式碼範例是自訂 WebServiceAuthenticationEvent
事件的委派 (Delegate)。
namespace Microsoft.WebServices.Security
{
using System;
public delegate void WebServiceAuthenticationEventHandler(Object sender, WebServiceAuthenticationEvent e);
}
下列程式碼範例為 XML Web Service 定義用戶端必須傳遞的 Authentication
SOAP 標頭。XML Web Service 不需要進行驗證,只要檢查 User.Identity.IsAuthenticated 屬性即可判斷 HTTP Module 是否已驗證使用者。
<%@ WebService Language="C#" Class="SecureWebService" %>
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
public class Authentication : SoapHeader {
public string User;
public string Password;
}
public class SecureWebService : WebService{
public Authentication authentication;
[WebMethod]
[SoapHeader("authentication")]
public string ValidUser(){
if (User.IsInRole("Customer"))
return "User is in role customer";
if (User.Identity.IsAuthenticated)
return "User is a valid user";
return "not authenticated";
}
}
下列程式碼範例為 XML Web Service 用戶端將必要的憑證傳遞給 Authentication
SOAP 標頭中的自訂 SOAP 標頭驗證方法。
// Create a new instance of an XML Web service proxy class.
SecureWebService s = new SecureWebService();
// Create the Authentication SOAP header and set values.
Authentication a = new Authentication();
a.User = user.Value;
a.Password = password.Value;
// Assign the Header.
s.AuthenticationValue = a;
string result = s.ValidUser();
span1.InnerHtml = result;
請參閱
設定 ASP.NET Web 應用程式的安全性 | ASP.NET 組態 | 使用 ASP.NET 建置 XML Web Service | NetworkCredential | CredentialCache | X509Certificate