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