Setting Web Services Security


Web service security and authentication is a difficult topic to tackle because the industry leaders are still defining the best approach for handling this task. As of this writing, Microsoft, IBM, and VeriSign have jointly released the WS-Security specification, which is a set of SOAP extensions that essentially define security tokens that accompany SOAP messages. This approach embodies the concept of federated security , which states that if a message comes from a trusted party and has not been tampered with, then it is a "secure" message. At a high level, this approach follows the successful path of the HTTPS approach. The HTTPS protocol uses certificates and tokens to provide "security" in two ways: by vouching for the integrity of the transmission ”in other words, by ensuring that the message has not been tampered with in transit ”and by vouching for the identity of the sending party. We are greatly oversimplifying federated security with this comparison, but it does begin to give you an idea about the technology.

Note

You can read more about Microsoft's Federated Security and Identity Roadmap at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwebsrv/html/wsfederate.asp .

Web services are special ASP.NET project types, so they can fully leverage the standard authentication schemes that ASP.NET provides, including Forms Authentication and Windows Authentication. We do not discuss this approach here because you can get whatever information you need from a standard discussion on ASP.NET security options. Instead, we are more intrigued by the possibilities that SOAP extensions provide for authenticating SOAP messages. This approach is particularly relevant given the role that SOAP extensions play in the WS-Security model.

SOAP headers are extensions to a SOAP envelope that are independent of the individual Web method messages. SOAP headers are useful for passing application-level information, such as authentication information, in a way that is independent of a specific Web method but instead applies to the entire Web service. ASP.NET makes it easy to work with SOAP headers, by providing a specialized SoapHeader base class, which is a member of the System.Web.Services.Protocols namespace. The steps for implementing a SOAP header in a Web service are as follows:

  1. Create a custom class in the Web service that derives from the SoapHeader base class.

  2. Add to the class one public property for each SOAP header being added.

  3. Add a SoapHeaderAttribute() to the Web method, which will process the SOAP header. This attribute includes a reference to the custom class. It also sets the direction of the SOAP header and whether it is required.

  4. Process the SOAP header inside the Web method.

Let's move straight into an example that demonstrates how SOAP headers can play a role in authenticating Web service requests . We have written a Web method that returns the most expensive product in the Northwind database. Assume that this is restricted information and that the client must provide an access code to receive the name of the most expensive product. The access code is stored in the Web.config file so that it can be updated easily.

Listing 6-6 is the abbreviated code for this Web service, which is called SecureNorthwind.asmx . You can find the full code in the WebService6B project in the sample code that accompanies this chapter. Note that the actual database retrieval code has been omitted for brevity.

Listing 6-6: The Abbreviated SecureNorthwind.asmx
start example
 Imports System.Configuration Imports System.Web.Services Imports System.Web.Services.Protocols Public Class APSoapHeader     Inherits SoapHeader     Public AccessCode As String End Class <WebService(Namespace:="http://tempuri.org/")> _ Public Class SecureNorthwind     Inherits System.Web.Services.WebService     Public objCSH As WebService6B.APSoapHeader     <WebMethod(), _         SoapHeaderAttribute("objCSH", Direction:=SoapHeaderDirection.In, _                  Required:=True)> _         Public Function GetMostExpensiveProduct() As String         Dim m_strAccessCode As String = ""         Dim m_strMostExpensiveProduct As String = ""         ' Retrieve the AccessCode value that is passed in the SOAP Header         m_strAccessCode = objCSH.AccessCode.ToString()         Try             If m_strAccessCode = ConfigurationSettings.AppSettings(_                           "WSAccessCode") Then                 ' Make a database call for the most expensive product                 ' Note, this detailed code listing is not shown                 m_strMostExpensiveProduct = <Retrieved from the database>             End If         Catch err As Exception         Finally         End Try         Return (m_strMostExpensiveProduct)     End Function End Class 
end example
 

Listing 6-6 includes a custom public class that defines the SOAP header, called APSoapHeader. This class defines a public member called AccessCode, which represents one collection element in the XML for the SOAP header. The Web method is called GetMostExpensiveProducts() , and it contains an instance of the custom class, APSoapHeader. The Web method also includes a SoapHeaderAttribute that sets the SOAP header as being input only and required. Notice that the full SOAP class itself is required and not just one member of the class. By extension, every member of the class that is defined must be passed in. (In this case, we have only one member, so we are technically implementing every available class member).

Now let's look at an ASP.NET client that calls this Web service (see Listing 6-7). The client page is called ap_WSGetMostExpensiveProduct.aspx and is included in the sample project AspNetChap6, which we worked with earlier. This listing makes use of a second Web reference to SecureNorthwind.asmx .

Listing 6-7: ap_WSGetMostExpensiveProduct.aspx
start example
 Private Sub Page_Load(ByVal sender As System.Object, _             ByVal e As System.EventArgs) Handles MyBase.Load         Dim strProduct As String         Dim objWS As localhost1.SecureNorthwind         Dim objCSH As localhost1.APSoapHeader         Try             ' Step 1: Instance the Web service and set its URL             objWS = New localhost1.SecureNorthwind()             objWS.Url = _             ConfigurationSettings.AppSettings("AspNetChap6.localhost1.SecureNorthwind")             ' Step 2: Instance the Soap Header, and set its AccessCode property             objCSH = New localhost1.APSoapHeader()             objCSH.AccessCode = _                ConfigurationSettings.AppSettings("WebServiceAccessCode")             ' Step 3: Assign the SoapHeader object to objWS.APSoapHeaderValue             objWS.APSoapHeaderValue = objCSH             ' Step 4: Retrieve the most expensive product             strProduct = objWS.GetMostExpensiveProduct()         Catch errSoap As System.Web.Services.Protocols.SoapException             Response.Write("SOAP Exception: " & errSoap.Message)         Finally         End Try End Sub 
end example
 

The code is more complicated than it appears. Quite simply, you have to set the access code property to a valid setting before you can submit a request to the Web method. The proxy class exposes a property on the Web service called AccessCodeValue (a variation of the original property name). The catch is that this property is of type APSoapHeader . So, you cannot just set a value and be done. Instead, you must create a new instance of APSoapHeader , populate it, and assign it to the Web service's AccessCodeValue property.

Accordingly, the client page must instance two separate objects. The first, objWS , references the Web service. The second, objCSH , references a new instance of the custom SOAP header class. The access code gets retrieved in the Web.config file and assigned to the objCSH.AccessCode property. Next, the object reference itself, objCSH, is assigned to the Web service's AccessCodeValue property. Finally, the actual target Web method is finally called.

If you fail to set the SOAP header, then you will receive the following exception message:

 Required field/property SecureNorthwind.APSoapHeaderValue of SOAP header APSoapHeader was not set by the client prior to making the call. 

If you set the SOAP header value correctly, then you will successfully receive the product name:

 Cte de Blaye 

It does not take much imagination to extend this approach to a more full-fledged security implementation. You could add separate input SOAP headers for username and password information and then validate it on the Web service side. You could also implement HTTPS transmission between the Web server and the Web service to ensure the privacy and integrity of the transmission. (Without HTTPS, a hacker with a network sniffer could discover the header contents and render them meaningless.) Of course, this approach assumes that the Web server and the remote Web service will stay synchronized with their authentication settings. There are many implications that we cannot begin to tackle here. Our point is simply to open your eyes to the possibilities that SOAP extensions provide for authenticating Web service requests. In the long run, the future of Web services security lies in federated security and the WS-Security specification mentioned earlier. You should make sure to stay informed on this important and evolving security specification.




Performance Tuning and Optimizing ASP. NET Applications
Performance Tuning and Optimizing ASP.NET Applications
ISBN: 1590590724
EAN: 2147483647
Year: 2005
Pages: 91

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net