Enforcing the correct IPrincipal and IIdentity with PrincipalPermission
I have defined a custom IPrincipal and custom IIdentity based on a website that defines both valid identities and their permissions. Both these classes are开发者_开发技巧 for use in a assembly used in a windows forms application.
The question is, when using the declarative PrincipalPermission attribute on top of my assembly classes, how to enforce that my custom IPrincipal and IIdentity classes are in use and not some other IPrincipal/IIdentity that might be Authenticated.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "limited")]
public class RequiresAuthentication
{ }
Security-aware code is split into two parts: the Identifying Party (IP), which authenticates users and generates IIdentity
and IPrincipal
objects, and the Relying Party (RP), which makes use of them.
In the RP, you don't care where the IPrincipal
came from, as long as it's valid.
You control where the permissions come from by writing the IP yourself. That way, you ensure that you only ever generate your custom IIdentity
and IPrincipal
objects.
If you call someone else's IP, you are by definition not caring what sort of IPrincipal
is generated.
EDIT:
Having said that, however, there is the additional problem that a role called "limited"
may be generated by several different IPs and mean different things to each one. The way to solve that problem is to use a claims-based principal rather than a role-based principal. A claim is not a simple string, but a generic data value that is digitally signed and identified by a namespace URI. That way, you still don't care which IPrincipal
is being given to you, but you can guarantee that the claim is the correct one even if its name clashes with some other claim from some other IP.
Have a look at the new Windows Identity Foundation (formerly called Geneva, formerly called Zermatt) for claims-based security.
You can't enforce that - that's the whole point of programming to an interface instead of concrete classes.
PrincipalPermission (and PrincipalPermissionAttribute) works on Thread.CurrentPrincipal, and since it follows the Liskov Substituion Principle it treats all IPrincipal instances equally.
If you really must ensure that only your own custom IPrincipal can be used, you could write your own CustomPrincipalPermission that mimics the behavior of PrincipalPermission.
We do much the same thing, with a custom principal and custom permission/attribute.
You can create a new attribute that derives from CodeAccessSecurityAttribute
and implement the CreatePermission
to return an instance of your own permission (deriving from IPermission
and IUnrestrictedPermission
) that implements the role-based checks. Then you mark up the methods with your own attribute rather than the standard one. One of the advantages of this is that you can use an enum for roles rather than having magic strings littered throughout the code.
[MyPrincipalPermission(SecurityAction.Demand, Roles = MyRoles.Limited)]
public void Foo() { ... }
Creating your own permission is the hard bit, and it really is quite complex to get all the Intersect
, Union
etc. methods working and tested, so if you're planning on going down this route then allocate somewhere in the region of 2-5 days to make sure this is rock solid.
精彩评论