This example demonstrates how to build aspects that automatically encrypt or decrypt parameter values. The only encryption algorithm implemented in this example is string reversal. This is not real encryption, of course! In practice, you would probably use a format-preserving encryption algorithm from a third party.
The FilterAttribute class is the abstract implementation of the aspect. It is not bound
to any encryption implementation algorithm. To implement a specific algorithm, you need
to derive a new class from FilterAttribute class. In this example, we just show
a ReserseAttribute aspect.
In some situations, for instance in ASP.NET MVC controllers, you may need to decrypt or
encrypt properties of a method parameter instead of the parameter itself (encrypting
an object is impossible; you can only either serialize its members with a format-preserving
algorithm, or the serialization of the object using binary encryption). For this scenario,
we have the ApplyFiltersAttribute, also derived from FilterAttribute. This custom
attribute causes the parameter value to be deeply decrypted or encrypted. You can apply
any filter attribute (either [Reverse] or [ApplyFilters] in this example) to
fields and properties of the parameter class.
What is being demonstrated?
The FilterAttribute class is more complex than it appears because it must support
two cases: encryption of parameter values and deep encryption of object trees. Under
the cover, the job is done by two separate aspects: FilterMethodArgumentsAspect and
FilterTypePropertiesAspect. However, we don't want to ask developers to choose between
the aspects. All we want to show to developers are front-end attributes derived
from the FilterAttribute class. Therefore, we use FilterAttribute as an
umbrella, hiding the implementation complexity. The FilterAttribute class whether
it has to provide a FilterMethodArgumentsAspect or
FilterTypePropertiesAspect aspect. This is done by implementing the IAspectProvider
interface.
The FilterMethodArgumentsAspect class is quite simple and is based on a
MethodInterceptionAspect. It is worth noting that we want to have a single
instance of the FilterMethodArgumentsAspect class per method, even if several parameters
are encrypted. The FilterAttribute has to provide the de-duplication. This is
done by using the IAspectRepositoryService service from PostSharp, which returns which
aspects have already been added to a declaration.
The FilterTypePropertiesAspect class is more complex. It introduces the IFilterable
interface into the target type, an interface which has a single method named ApplyFilters.
To have access to fields and properties at runtime without reflection, the aspect
relies on an IAdviceProvider which provides a set of ImportLocationAdviceInstance
advices: one for each encrypted property. At runtime, the bindings field of the aspect class
is populated with a List<ILocationBinding>, which gives access to all properties.