I work in WCF and am writing my Authentication Manager which is based on IHttpModule
and it works fine. One the of methods in my Authentication
class creates a GenericPrincipal
object in Context.User
.
For example
app.Context.User = new GenericPrincipal(new GenericIdentity("Scott"), new string[] { "read" });
In one of methods in Service
I want to assign the user PrincipalPermissionAttribute
and I don't how it should work, but it always throws a SecurityException
. For example:
[WebGet(UriTemplate = "/", RequestFormat=WebMessageFormat.Xml, ResponseFormat=WebMessageFormat.Xml)]
[PrincipalPermission(SecurityAction.Demand, Role="read")] // it throw SecurityException
public SampleItem GetCollection()
{
bool user = HttpContext.Current.User.IsInRole("read"); // return true
bool user1 = HttpContext.Current.User.IsInRole("write"); // return false
return SampleItem.GetSampleItem();
}
Maybe PrincipalPremissionAttribute
doesn't use Context.Current.User
? But if not then what?
I tried remove the problem, and made a very simple attribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple=true, Inherited=false)]
public class MyAuthorizationAttribute : Attribute
{
public MyAuthorizationAttribute(params string[] roles)
{
foreach (string item in roles)
{
if(HttpContext.Current.User.IsInRole(item) == false)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.AddHeader("WWW-Authenticate", "Basic Realm");
HttpContext.Current.Response.StatusDescription = "Access Denied";
HttpContext.Current.Response.Write("401 Access Denied");
HttpContext.Current.Response.End();
}
}
}
}
But the application can't use this. What I mean is, when I set a breakpoint on the MyAttribute
constructor, the compiler doesn't stop on the beakpoint, it doesn't see it.
[WebGet(UriTemplate = "/", RequestFormat=WebMessageFormat.Xml, ResponseFormat=WebMessageFormat.Xml)]
[MyAuthorization("read")]
public SampleItem GetCollection()
{
bool user = HttpContext.Current.User.IsInRole("read"); // return true
bool user1 = HttpContext.Current.User.IsInRole("write"); // return false
return SampleItem.GetSampleItem();
}
With WCF you need to associate custom principals via a very specific mechanism, which works fine. Note also that attributes generally do not cause code execution, and only get invoked when done explicitly done via reflection (unless you are using PostSharp). You can't just add an attribute and have it do things automatically. MVC etc gives that impression, but there is code in MVC checking for attributes and executing them manually.