Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Enhance Your Multi-tier Applications with the Windows Communication Foundation  : Page 3

By making simple modifications to XML-based WCF configuration files, you can add security, transactability, and reliability to multi-tier applications nearly instantly.

The Application—Business Logic Tier
It is the responsibility of the business logic tier to provide the middleware in any system. This is a crucial layer, as it protects and enriches the back end data resources, as well as providing accessibility to the presentation layer that the user ultimately sees. In a typical scenario, the business logic layer integrates disparate data sources, and adds value to them through analytics or other functions. In a chat system, for example, the business logic layer would provide granular permissioning.

In this demonstration system, there appears to be little difference between the business logic layer and the data-access layer. The business logic layer does little more than perform a pass-through. This is actually quite a common practice—and a recommended one—because as requirements for application functionality grow, the layer separation is already in place, and the data-access tier would require little or no modification.

The business logic layer in this sample does handle establishing the secure identity of the client. Because this tier protects the database, any access to this layer should be sanitized, in other words, it should be accessible only by authenticated users. Security is paramount, so the system must ensure that users are who they say they are. In this example, the application assumes that users are already logged in to the corporate network; the client tier passes their corporate identity to the business logic tier. Thus, anyone without access to the corporate network would not be able to access this business logic. This is important not only for security, but also for the user experience; with this scheme, users don't need a separate set of sign-in credentials to be able to access the Chat system, nor does the corporate administrator need to keep an eye on a completely different set of credential systems, exposing a larger attack surface.

Here's the business logic tier code.

[ServiceContract(Namespace= "http://Devx.Indigo.Samples")] public interface IChatService { [OperationContract] string GetBackChat(int nMessageID); [OperationContract] bool InsertMessage(string strMsg); [OperationContract] decimal GetMostRecentMessageID(); } public class ChatService : IChatService { public string GetBackChat(int nMessageID) { ChatResourceProxy chatResource = new ChatResourceProxy(); return chatResource.GetBackChat(nMessageID); } public bool InsertMessage(string strMessage) { string strUserID = Thread.CurrentPrincipal.Identity.Name; ChatResourceProxy chatResource = new ChatResourceProxy(); return chatResource.InsertMessage( strUserID, strMessage); } public decimal GetMostRecentMessageID() { ChatResourceProxy chatResource = new ChatResourceProxy(); return chatResource.GetMostRecentMessageID(); } }

Note that, similar to the data-access tier, there's no code written specifically for security in the preceding code. Also notice, as previously mentioned, that this code is largely pass through. One minor, but important difference is in the InsertMessage function. This function exposes a different footprint to the client—one that doesn't expect the user identity to be passed in. (Compare it with the one in the data-access tier (see Listing 1) that does expect a user identity argument). In this case, to implement a secure system, you don't want to expose the identity API to callers, thus giving them a chance to pass in fake credentials. You want the credentials to be managed by WS-Security APIs and not your own API.

The implementation of the InsertMessage function then pulls the user's ID from the Thread.CurrentPrinicapal.Identity property. The ServiceModel provides the user's ID to that method. How does it do this? Again, it's declarative and not programmed. The Web.config for the business logic tier shows you how to accomplish this:

<services> <service type="ChatService" behaviorConfiguration="returnFaults"> <endpoint contract="IChatService" binding="wsHttpBinding" bindingConfiguration="Binding1"/> </service> </services> <behaviors> <behavior name="returnFaults" returnUnknownExceptionsAsFaults="true" /> </behaviors> <bindings> <wsHttpBinding> <binding name="Binding1"> <security mode="Message"> <message clientCredentialType="Windows"/> </security> </binding> </wsHttpBinding> </bindings>

Notice that the ChatService class shown earlier calls the data-access tier using a ChatResourceProxy object. This proxy is created automatically using the svcutil tool provided by WCF. When you create and implement a WCF service, it has an associated WSDL file. To create a client accessor, you simply run svcutil and pass it the location of the WSDL as a parameter. Doing that creates two files—a .cs file containing the proxy, and a file called Output.config containing the configuration that the ServiceModel needs to access the service. Simply add the contents of Output.config to your Web.config or App.config (the former if your client is a Web application, the latter if it is a WinForms application) and WCF will handle the communication for you.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.