Friday, 31 August 2012

WCF - Notes 5 Security and Transactions


Security

  • Exposing services on a network, even an internal network, usually requires some kind of security. How can the service be certain of its client’s identity? How can messages sent to and from a service be kept safe from malicious changes and prying eyes? And how can access to a service be limited to only those authorized to use it? Without some solution to these problems, it’s too dangerous to expose many kinds of services. Yet building secure distributed applications is difficult. Ideally, there should be straightforward ways to address common security scenarios, along with more fine-grained control for applications that need it.
  • To help achieve this, WCF provides the core security functions of authentication, message integrity, message confidentiality, and authorization. All of these depend fundamentally on the notion of identity: who is this user? Establishing an identity for a client or service requires supplying information such as a username and password, an X.509 certificate, or something else. A client or service can do this by directly invoking a WCF function, by using a config file, or in other ways, such as by referencing a certificate store. However it’s done, establishing an identity is an essential part of using WCF security.
  • Distributed security can get very complicated very fast. A primary goal of WCF’s designers was to make building secure applications easier. To allow this, WCF’s approach to authentication, data integrity and data privacy relies on bindings. Rather than require developers to insert the right attributes to secure each class and method, they can instead just use a binding that provides the right set of security services. A developer’s choices include the following:
  • Use a standard binding that directly supports security. For example, applications that require end-to-end security for messages that go through multiple SOAP intermediaries can use a binding that supports WS-Security, such as WsHttpBinding.
  • Use a standard binding that optionally supports security, then configure it as needed. For example, applications that need only transport-based security can choose BasicHttpBinding, configuring it to use HTTPS rather than HTTP. It’s also possible to customize other more-advanced security behaviors. For example, the authentication mechanism used by a binding such as WsHttpBinding can be changed if desired.
  • Create a custom binding that provides exactly the security behavior a developer needs. Doing this is not for the faint of heart, but it can be the right solution for some problems.
  • Use a standard binding that provides no support for security, such as BasicHttpBinding. While using no security is often a risky thing to do, it can sometimes be the only option.
<configuration>
  <system.serviceModel>
    <services>
      <service
        type="RentalReservations,RentalApp"
        <endpoint
          contract="IReservations"
          binding="basicHttpBinding"
          bindingConfiguration="UsingHttps"
          address=
            ”http://www.fabrikam.com/reservation/reserve.svc"/>
      </service>
    </services>
    <bindings>
        <basicHttpBinding>
        <binding
          configurationName="UsingHttps"
          securityMode="Https"/>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>
  • A WCF service can also control which clients are authorized to use its services. To do this, WCF relies on existing authorization mechanisms in the .NET Framework. A service can use the standard PrincipalPermission attribute, for example, to define who is allowed to access it. Alternatively, a WCF application that needed role-based authorization could use Windows Authorization Manager to implement this.
  • Transactions
  • Handling transactions is an important aspect of building many kinds of business logic. Yet using transactions in a service-oriented world can be problematic. Distributed transactions assume a high level of trust among the participants, so it often isn’t appropriate for a transaction to span a service boundary. Still, since there are situations where combining transactions and services makes sense, WCF includes support for this important aspect of application design.
  • Transactions in the .NET Framework: System.Transactions
  • The transaction support in WCF builds on System.Transactions, a .NET Framework namespace focused solely on controlling transactional behaviors. Although it’s not required, developers commonly use the services of System.Transactions in concert with an execution context. An execution context allows the specification of common information, such as a transaction, that applies to all code contained within a defined scope. Here’s an example of how an application can use this approach to group a set of operations into a single transaction:
using System.Transactions;
using (TransactionScope ts =
   new TransactionScope(TransactionScopeOption.Required)) {
   // Do work, e.g., update different DBMSs
   ts.Complete();
}
  • All of the operations within the using block will become part of a single transaction, since they share the transactional execution context it defines. The last line in this example, calling the TransactionScope‘s Complete method, will result in a request to commit the transaction when the block is exited. This approach also provides built-in error handling, aborting the transaction if an exception is raised.
  • Specifying TransactionScopeOption.Required for the new TransactionScope, as this example does, means that this code will always run as part of a transaction: joining its caller’s transaction if one exists, creating a new one if it does not.
  • Unlike Enterprise Services and its predecessors Microsoft Transaction Server (MTS) and COM+, however, System.Transactions is focused entirely on controlling transactional behavior. There is no required connection between a transaction and the internal state of an object, for example. While Enterprise Services requires an object to be deactivated when it ends a transaction, System.Transactions makes no such demand. Since WCF builds on System.Transaction, WCF-based applications are also free to manage transactions and object state independently.
  • WCF-based applications can use the types in System.Transactions directly, or they can control transactions using WCF-defined attributes that rely on System.Transactions under the covers. 
  •  A service’s methods can control transactional behavior via an attribute. Rather than explicitly relying on System.Transactions, a service can use the OperationBehavior attribute described earlier.
[OperationContract]
[OperationBehavior(TransactionScopeRequired=true,
                   TransactionAutoComplete=true)]
private int Reserve(int vehicleClass, int location, string dates)
{
  int confirmationNumber;
  // logic to reserve rental car goes here
  return confirmationNumber;
}
  • Finally, it’s worth emphasizing that applications built on WCF can participate in transactions that include applications running on non-WCF platforms. For example, a WCF-based application might start a transaction, update a record in a local SQL Server database, then invoke a Web service implemented on a Java EE-based application server that updates a record in another database. If this service is transactional and the platform it’s running on supports the WS-AtomicTransaction specification, both database updates can be part of the same transaction. Like security and reliable messaging, WCF transactions can work in the heterogeneous world that Web services make possible.

No comments:

Post a Comment