PrincipalPermissionAttribute and custom IPrincipal

A

Andrew Jocelyn

Hi

I want to use the PrincipalPermissionAttribute to protect classes and
methods in my business logic layer. I have custom IPrinciple and IIdentity
classes and I'm not sure what I need to do to make thenm compatible with the
PrincipalPermissionAttribute.

public class SitePrincipal : System.Security.Principal.IPrincipal
{
public SitePrincipal(int accountID)
{
_identity = new SiteIdentity(accountID);
_role = "Special";
}
}

At the moment the above class is called in a web page OnPreInit event:

Context.User = new SitePrincipal(1773);

The class is authenticated.

[PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role =
"Special")]
public class MyClassBLL
{}

What do I need to do to get my custom IPrincipal to work with the
PrincipalPermissionAttribute class? At the moment the test fails the
security check. Is there some test code I could use to debug with? I'm not
sure of the best way when working with attributes.

Thanks
Andrew
 
A

Allen Chen [MSFT]

Hi Andrew,

The key to do this is to set Thread.CurrentPrincipal instead of
Context.User. Here's a sample. For the simplicity I hard coded the role.
The following code only allows Role1 to access MYBLL. You can try to change
[PrincipalPermission(SecurityAction.Demand,Role="Role2")] to see the effect.

Aspx:
<asp:Button ID="Button1" runat="server" Text="Button"
onclick="Button1_Click" />

Aspx.cs:

[PrincipalPermission(SecurityAction.Demand,Role="Role1")]
public class MYBLL
{

}
public partial class _Default : System.Web.UI.Page
{
protected void Page_PreInit(object sender, EventArgs e)
{
Thread.CurrentPrincipal=new SitePrincipal(1773);

}

protected void Button1_Click(object sender, EventArgs e)
{
MYBLL test = new MYBLL();
}
}
public class SitePrincipal : System.Security.Principal.IPrincipal
{
public SitePrincipal(int accountID)
{
_identity = new SiteIdentity(accountID);
}
#region IPrincipal Members
SiteIdentity _identity;
public System.Security.Principal.IIdentity Identity
{
get { return _identity; }
}
public bool IsInRole(string role)
{
if (role == "Role1")
return true;
else { return false;
}
}

#endregion
}
public class SiteIdentity : IIdentity
{
string _name;
public SiteIdentity(int accountID)
{
_name = accountID.ToString();

}
#region IIdentity Members

public string AuthenticationType
{
get { throw new NotImplementedException(); }
}

public bool IsAuthenticated
{
get { return true; }
}

public string Name
{
get { return _name; }
}

#endregion
}

Please have a try and let me know if it works. If you have additional
questions please feel free to ask.

Regards,
Allen Chen
Microsoft Online Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
B

bruce barker

this does not seem safe. if asp.net does a thread switch during the
request, then Thread.CurrentPrincipal is reset by
HttpApplication.OnThreadEnter. shouldn't the code be in
Application_AuthenticateRequest where you set both context and thread
prinicpal?


-- bruce (sqlwork.com)
Hi Andrew,

The key to do this is to set Thread.CurrentPrincipal instead of
Context.User. Here's a sample. For the simplicity I hard coded the role.
The following code only allows Role1 to access MYBLL. You can try to change
[PrincipalPermission(SecurityAction.Demand,Role="Role2")] to see the effect.

Aspx:
<asp:Button ID="Button1" runat="server" Text="Button"
onclick="Button1_Click" />

Aspx.cs:

[PrincipalPermission(SecurityAction.Demand,Role="Role1")]
public class MYBLL
{

}
public partial class _Default : System.Web.UI.Page
{
protected void Page_PreInit(object sender, EventArgs e)
{
Thread.CurrentPrincipal=new SitePrincipal(1773);

}

protected void Button1_Click(object sender, EventArgs e)
{
MYBLL test = new MYBLL();
}
}
public class SitePrincipal : System.Security.Principal.IPrincipal
{
public SitePrincipal(int accountID)
{
_identity = new SiteIdentity(accountID);
}
#region IPrincipal Members
SiteIdentity _identity;
public System.Security.Principal.IIdentity Identity
{
get { return _identity; }
}
public bool IsInRole(string role)
{
if (role == "Role1")
return true;
else { return false;
}
}

#endregion
}
public class SiteIdentity : IIdentity
{
string _name;
public SiteIdentity(int accountID)
{
_name = accountID.ToString();

}
#region IIdentity Members

public string AuthenticationType
{
get { throw new NotImplementedException(); }
}

public bool IsAuthenticated
{
get { return true; }
}

public string Name
{
get { return _name; }
}

#endregion
}

Please have a try and let me know if it works. If you have additional
questions please feel free to ask.

Regards,
Allen Chen
Microsoft Online Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
A

Allen Chen [MSFT]

Hi Bruce,

Thanks for your comments. As far as I know the thread will not be switched
between the Page_PreInit and the postback event. The only possibility is to
use async handler:

http://msdn.microsoft.com/en-us/magazine/cc163725.aspx

Moreover, even if thread is switched the principal will be maintained.

http://www.lhotka.net/WeBlog/PermaLink,guid,019e3c37-38ed-492e-b769-16e1a57f
ed0a.aspx

But in my code I'm using the sync one so it has no thread switching issue.
From my code we can see actually the PrincipalPermission requires
Thread.CurrentPrincipal instead of Context.User to perform the demand.
Since Andrew put the code in Page_Init I think it would be easier for him
to test.

If you try the following code in global.asax it will not work:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
Thread.CurrentPrincipal = new SitePrincipal(1773);
//In this case it should be Context.User = new
SitePrincipal(1773);
//the Thread.CurrentPrincipal will be set the same as the
Context.User in OnThreadEnter.
}

Because the Thread.CurrentPrincipal will be reset after this, in the
OnThreadEnter():

http://www.hanselman.com/blog/SystemThreadingThreadCurrentPrincipalVsSystemW
ebHttpContextCurrentUserOrWhyFormsAuthenticationCanBeSubtle.aspx

However, I agree that the code is not a good practice. It would be better
to write a HttpModule to do this task.

Regards,
Allen Chen
Microsoft Online Support
 
A

Allen Chen [MSFT]

Hi Andrew,

Have you tested my code? Can it work?

Regards,
Allen Chen
Microsoft Online Community Support
 
A

Andrew Jocelyn

Hi Allen

Yes changing Context.User to Thread.CurrentPrincipal works.

I'm going to look at creating an HttpModule for this. Look's like the best
option, as you suggest.

Thanks
Andrew
 
A

Allen Chen [MSFT]

Glad to know that, Andrew. If you have additional questions about the
HttpModule please feel free to let me know.

Thank you for using our Newsgroup Support Service!

Regards,
Allen Chen
Microsoft Online Community Support
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top