It isn't long into a discussion about Web Services that I'm asked about security. In one class I taught, this question came up within five minutes. (This question, though, usually comes from UNIX developers because they love to taunt Microsoft developers after the many Windows security issues.)
Although it's well and good to make Web Services discoverable and easily used, this may not be the best thing for your enterprise application. Consider, for instance, a credit-card authorization Web Service. If it is openly discoverable and usable from anywhere on the Web, anyone can use it, whether for legitimate or unscrupulous purposes. For this reason, Web Services must be protected in many cases.
There are some security issues for Web Services: authentication, authorization, message integrity, and non-repudiation. Authentication is the process of validating identity based on credentials. Authorization determines whether an identity has access to a given resource. In this section, we'll deal with authentication, and how to verify a user's credentials.
For secure authentication and data transfer, SSL can be used with a Web Service the same as with Web pages. The two things necessary for this to happen are an SSL certificate that has been properly installed on the server and access to the Web Service with the https:// protocol specifier (instead of http://).
A Web Service must be made to require authentication, or any client request will be granted without the need for credential authentication. This is most easily done from the Internet Service Manager console. To require authentication, right click the Web Service directory and select Properties. Click the Directory Security tab, and click the Edit button in the section entitled "Anonymous access and authentication control." Deselect the "Anonymous access" check box, as shown in Figure 14.11.
Figure 14.11. You Must Deselect the "Anonymous access" Check Box for Internet Information Server to Require Authentication.
The client code with which you access Web Services that require authentication will need some additions over the simple "instantiate and use" code we've seen to this point in the chapter. First, a CredentialCache object must be created. This object is what ASP.NET uses to transport groups of credentials when authenticating to Web resources. The following code shows the creation of a CredentialCache object:C#
CredentialCache credentialCache = new CredentialCache();VB
Dim credentialCache as new CredentialCache()
A NetworkCredential object must then be created and must contain the user credentials that will be used to authenticate. The following code creates a NetworkCredential object with credentials:C#
NetworkCredential credentials = new NetworkCredential("Administrator", "rocknet2","WORKGROUP");VB
Dim credentials as new NetworkCredential("Administrator","rocknet2", "WORKGROUP")
Once you have CredentialCache and NetworkCredential objects, you need to add the NetworkCredentials object to the CredentialCache object. When you do this, you'll need to specify the URL for the resource to which you'll be seeking access, the authentication type, and the NetworkCredential object that you want to use. The following code shows how to call the CredentialCache.Add() method. It obtains the URL from the Web Service class Url property. It specifies NTLM authentication.C#
credentialCache.Add(new Uri(svc.Url), "NTLM", credentials);VB
credentialCache.Add(new Uri(svc.Url), "NTLM", credentials)
The last thing you must do before making calls to the Web Service's methods is the set the Web Service class's Credentials property. Simply assign it the CredentialCache object that you created. The following code shows how to do this, and a complete C# example can be seen in Listing 14.11:C#
svc.Credentials = credentialCache;VB
svc.Credentials = credentialCache
Listing 14.11 Here You Can See the Complete Process for Instantiating a Web Service, Creating the Credentials Objects, and Calling a Web Service Method.
// Create a new instance of the Web Service class. localhost.Service1 svc = new localhost.Service1(); // Create a new instance of CredentialCache. CredentialCache credentialCache = new CredentialCache(); // Create a new instance of a NetworkCredential object. NetworkCredential credentials = new NetworkCredential("Administrator", "rocknet2","WORKGROUP"); // Add the NetworkCredential to the CredentialCache. credentialCache.Add(new Uri(svc.Url), "NTLM", credentials); // Add the CredentialCache to the Web Service class credentials. svc.Credentials = credentialCache; // Call the method on the proxy class. string strResult = svc.HelloWorld();