Thursday, March 22, 2012

web.config, roles and multiple directories

Hi,
here is what I'm trying to do: I have a virtual directory called
"WebApp". Under this one I've got 2 physical directories called
"Customers" and "Admins".
I implemented Forms-based authentication. If the logon credentials are
ok, I transfer the user to either the "Customers" or the "Admins"
subdirectory. Those two directories should have a web.config file, which
allows the roles "Admins" and "Customers" access the resources in the
directories.
But I can't figure out how to set the Role when I create the Ticket for
the guy logging on during authentification.
Can anybody help me out?
Thanks in advance...
MatthiasYou don't set roles at authentication time... I know, it's a bit strange.
Instead you typically set the roles in global.asax in the Application_Authen
ticateRequest
event as such:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
if (User.Identity.Name == "brock")
{
string[] roles = new string[2];
roles[0] = "Admin";
roles[1] = "Doctor";
Context.User =
new System.Security.Principal.GenericPrincipal(User.Identity,
roles);
}
}
}
This is hard coded for a specific name, so you'd normally go look this up
in the DB based upon User.Identity.Name. One note: this is called for every
request into your application, so going to the DB every time is going to
be expensive. I'd suggest caching the roles (probabaly in the ASP.NET Cache
object).
-Brock
DevelopMentor
http://staff.develop.com/ballen

> Hi,
> here is what I'm trying to do: I have a virtual directory called
> "WebApp". Under this one I've got 2 physical directories called
> "Customers" and "Admins".
> I implemented Forms-based authentication. If the logon credentials are
> ok, I transfer the user to either the "Customers" or the "Admins"
> subdirectory. Those two directories should have a web.config file,
> which allows the roles "Admins" and "Customers" access the resources
> in the directories.
> But I can't figure out how to set the Role when I create the Ticket
> for the guy logging on during authentification.
> Can anybody help me out?
> Thanks in advance...
> Matthias
>
Matthias, is there a reason you are using three different web.config
files? You could do it all in one. You can deny access to each of the
Customers or Admins directories and redirect them based on their acces
role.
Jason Bentley
[url]http://gswithblogs.net/jbentley[/url]
Hi Jason,
I'll go and read about it. Thanks for the hint!
Matthias
Jason Bentley wrote:
> Matthias, is there a reason you are using three different web.config
> files? You could do it all in one. You can deny access to each of the
> Customers or Admins directories and redirect them based on their acces
> role.
> Jason Bentley
> [url]http://gswithblogs.net/jbentley[/url]
>
Hi Brock,
thanks for your reply. In the meantime I've been looking for a different
solution and found something, but I'm not sure whether this is secure:
I only have a couple of pages in those subdirectories. So I would go for
setting my role-identifier as the UserData in the
FormsAuthenticationTicket when I authenticate the user. Later I'd go and
check (on each and every page) whether the user belongs to the role that
can actually access the specified page.
If I encrypt the ticket, would it be safe to store the role in the UserData?
Again, thanks for your help.
Matthias
Brock Allen wrote:
> You don't set roles at authentication time... I know, it's a bit
> strange. Instead you typically set the roles in global.asax in the
> Application_AuthenticateRequest event as such:
> protected void Application_AuthenticateRequest(Object sender, EventArgs e)
> {
> if (Request.IsAuthenticated)
> {
> if (User.Identity.Name == "brock")
> {
> string[] roles = new string[2];
> roles[0] = "Admin";
> roles[1] = "Doctor";
> Context.User =
> new
> System.Security.Principal.GenericPrincipal(User.Identity, roles);
> }
> }
> }
> This is hard coded for a specific name, so you'd normally go look this
> up in the DB based upon User.Identity.Name. One note: this is called for
> every request into your application, so going to the DB every time is
> going to be expensive. I'd suggest caching the roles (probabaly in the
> ASP.NET Cache object).
> -Brock
> DevelopMentor
> http://staff.develop.com/ballen
>
>
>
>
Yes of course you could take this approach too. You'd still need to handle
Application_AuthenticateRequest to read the data from the cookie and then
construct the GenericPrincipal and assign it into the HttpContext.Current.Us
er.
-Brock
DevelopMentor
http://staff.develop.com/ballen
> Hi Brock,
> thanks for your reply. In the meantime I've been looking for a
> different solution and found something, but I'm not sure whether this
> is secure:
> I only have a couple of pages in those subdirectories. So I would go
> for setting my role-identifier as the UserData in the
> FormsAuthenticationTicket when I authenticate the user. Later I'd go
> and check (on each and every page) whether the user belongs to the
> role that can actually access the specified page.
> If I encrypt the ticket, would it be safe to store the role in the
> UserData?
> Again, thanks for your help.
> Matthias
> Brock Allen wrote:
>
Hi Brock,
I don't understand, why I would need to handle the
Application_AuthenticateRequest. Is it not sufficient to just have code
like this in the Page_Load event of every page in the subdirectories:
I assume the RoleID is a numeric value and has been placed in the
Tickets UserData property.
+++
FormsIdentity identity = (FormsIdentity) Page.User.Identity;
if(identity.IsAuthenticated) {
int nRoleID = int.Parse(identity.Ticket.UserData);
if (nRoleID == 1) {
// the user is an admin
}
else {
// authenticated, but not an admin
}
}
else {
// not authenticated...
}
+++
I've played around with it and it seems to work. Sorry for buzzering but
I'd just like to get this straight for me.
Again, thanks for your help!
Matthias
Brock Allen wrote:
> Yes of course you could take this approach too. You'd still need to
> handle Application_AuthenticateRequest to read the data from the cookie
> and then construct the GenericPrincipal and assign it into the
> HttpContext.Current.User.
> -Brock
> DevelopMentor
> http://staff.develop.com/ballen
>
>
>
>
The main reason is that you're missing out on the declarative authorization
in web.config. In web.config you can put:
<authorization>
<allow roles="Admin" />
<deny users="*" />
</authorization>
The huge win here is that you *don't* have to check in each page. It's check
ed
for you based upon your declarative settings. This is what I was referring
to before when I said you don't have to do all of this work yourself. But,
to make the built-in check work for you, you need to build the role list
in a GenericPrincipal and assign it to the HttpContext.Current.User in Appli
cation_AuthenticateRequest.
-Brock
DevelopMentor
http://staff.develop.com/ballen
> Hi Brock,
> I don't understand, why I would need to handle the
> Application_AuthenticateRequest. Is it not sufficient to just have
> code like this in the Page_Load event of every page in the
> subdirectories:
> I assume the RoleID is a numeric value and has been placed in the
> Tickets UserData property.
> +++
> FormsIdentity identity = (FormsIdentity) Page.User.Identity;
> if(identity.IsAuthenticated) {
> int nRoleID = int.Parse(identity.Ticket.UserData);
> if (nRoleID == 1) {
> // the user is an admin
> }
> else {
> // authenticated, but not an admin
> }
> }
> else {
> // not authenticated...
> }
> +++
> I've played around with it and it seems to work. Sorry for buzzering
> but I'd just like to get this straight for me.
> Again, thanks for your help!
> Matthias
> Brock Allen wrote:
>

0 comments:

Post a Comment