G
Guest
Hello,
We have encountered some obscure and unexpected behavior of
PrincipalPermissionAttribute, if applied to both a class as well as a method
in this class. The class permission seems to form an inclusive or with the
method permission.
We have a different scenario ourselves, but we will take an example of MS:
http://weblogs.asp.net/scottgu/arch...yers-using-PrincipalPermissionAttributes.aspx
<quote>
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
[PrincipalPermission(SecurityAction.Demand, Role = "HR")]
public void AddEmployee(Employee e)
{
// todo
}
}
In the above example, I have added a PrincipalPermission attribute to the
"EmployeeManager" class. By adding it I am requiring that a user must be
authenticated (logged-in) before this class can be instantiated during a web
request (the Authenticated=true demand enforces this). I have also then
added two additional security demands on the "LookupEmployee" and
"AddEmployee" methods. With the LookupEmployee method I am requiring that
the authenticated user for the request is within the "Manager" role in order
for the method to be invoked. With the AddEmployee method I am requiring
that the authenticated user for the request is within the "HR" role in order
for this method to be invoked and have a new Employee added to the
system.</quote>
Unfortunately this does not seem to work. Access to LookupEmployee is now
provided to ALL USERS WHO ARE AUTHENTICATED.
See testcode below.
My question:
- Am I missing something here? And, if not:
-> Is this by design? If so, this may be reconsidered because many people
are missing the point here
-> Is there a workaround. In our case, we want to provide access to class C
if the user is a member of role A or B. Moreover we only want to provide
access to method RequireB if the user is a member of role B. Hence, if the
user is in role A but not in B, it can access the class but not the method
RequireB. How could this be achieved declaratively [using standard framework
objects, because otherwise we are required to deploy our custom permission in
the GAC]
Regards,
Martijn Kaag
Testcode. Call Submit2MSDN.Test() to reproduce:
class Submit2MSDN
{
public static void Test1()
{
try
{
System.Threading.Thread.CurrentPrincipal = new
GenericPrincipal(new GenericIdentity("Not A Manager"), new string[] { "HR"});
EmployeeManagerNew man = new EmployeeManagerNew ();
man.LookupEmployee(1);
throw new InvalidOperationException("Test 1 failed.");
}
catch (SecurityException)
{
// as expected
}
}
public static void Test2()
{
try
{
System.Threading.Thread.CurrentPrincipal = new
GenericPrincipal(new GenericIdentity("Not A Manager"), new string[] { "HR" });
EmployeeManager man = new EmployeeManager();
man.LookupEmployee(1);
throw new InvalidOperationException("Test 2 failed.");
}
catch (SecurityException)
{
// as expected
}
}
public static void Test()
{
Test1(); // Succeeds
Test2(); // Fails!!!!!!!!!!
}
}
public class Employee { }
// No permission here
public class EmployeeManagerNew
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
}
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
[PrincipalPermission(SecurityAction.Demand, Role = "HR")]
public void AddEmployee(Employee e)
{
// todo
}
}
We have encountered some obscure and unexpected behavior of
PrincipalPermissionAttribute, if applied to both a class as well as a method
in this class. The class permission seems to form an inclusive or with the
method permission.
We have a different scenario ourselves, but we will take an example of MS:
http://weblogs.asp.net/scottgu/arch...yers-using-PrincipalPermissionAttributes.aspx
<quote>
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
[PrincipalPermission(SecurityAction.Demand, Role = "HR")]
public void AddEmployee(Employee e)
{
// todo
}
}
In the above example, I have added a PrincipalPermission attribute to the
"EmployeeManager" class. By adding it I am requiring that a user must be
authenticated (logged-in) before this class can be instantiated during a web
request (the Authenticated=true demand enforces this). I have also then
added two additional security demands on the "LookupEmployee" and
"AddEmployee" methods. With the LookupEmployee method I am requiring that
the authenticated user for the request is within the "Manager" role in order
for the method to be invoked. With the AddEmployee method I am requiring
that the authenticated user for the request is within the "HR" role in order
for this method to be invoked and have a new Employee added to the
system.</quote>
Unfortunately this does not seem to work. Access to LookupEmployee is now
provided to ALL USERS WHO ARE AUTHENTICATED.
See testcode below.
My question:
- Am I missing something here? And, if not:
-> Is this by design? If so, this may be reconsidered because many people
are missing the point here
-> Is there a workaround. In our case, we want to provide access to class C
if the user is a member of role A or B. Moreover we only want to provide
access to method RequireB if the user is a member of role B. Hence, if the
user is in role A but not in B, it can access the class but not the method
RequireB. How could this be achieved declaratively [using standard framework
objects, because otherwise we are required to deploy our custom permission in
the GAC]
Regards,
Martijn Kaag
Testcode. Call Submit2MSDN.Test() to reproduce:
class Submit2MSDN
{
public static void Test1()
{
try
{
System.Threading.Thread.CurrentPrincipal = new
GenericPrincipal(new GenericIdentity("Not A Manager"), new string[] { "HR"});
EmployeeManagerNew man = new EmployeeManagerNew ();
man.LookupEmployee(1);
throw new InvalidOperationException("Test 1 failed.");
}
catch (SecurityException)
{
// as expected
}
}
public static void Test2()
{
try
{
System.Threading.Thread.CurrentPrincipal = new
GenericPrincipal(new GenericIdentity("Not A Manager"), new string[] { "HR" });
EmployeeManager man = new EmployeeManager();
man.LookupEmployee(1);
throw new InvalidOperationException("Test 2 failed.");
}
catch (SecurityException)
{
// as expected
}
}
public static void Test()
{
Test1(); // Succeeds
Test2(); // Fails!!!!!!!!!!
}
}
public class Employee { }
// No permission here
public class EmployeeManagerNew
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
}
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public class EmployeeManager
{
[PrincipalPermission(SecurityAction.Demand, Role = "Manager")]
public Employee LookupEmployee(int employeeID)
{
return null;
}
[PrincipalPermission(SecurityAction.Demand, Role = "HR")]
public void AddEmployee(Employee e)
{
// todo
}
}