Alternative to Roles.IsUserInRole("rolename") using Web.config location element

461 Views Asked by At

Let me start by saying that what I have works - I just don't like it.

I have a web.sitemap that is used for my navigation bar. Some of the nodes are accessible by everyone, some of them have roles assigned (so that the node won't be shown to users who wouldn't be able to access it).

i.e. <siteMapNode url="~/adminpage.aspx" title="admin" roles="domain\Administrators"/>

Then, in my web.config, I have location elements like this:

<location path="adminpage.aspx">
  <system.web>
    <authorization>
      <allow roles="domain\Administrators"/>
      <deny roles="*"/>
    </authorization>
  </system.web>
</location>

In addition to this, some pages have hyperlinks that are shown or hidden based on roles, like this:

myHyperlink.Visible = Roles.IsUserInRole(@"domain\Administrators");

All of this works just fine - but... it seems a bit ridiculous. Is there any way to utilize the permissions established in my Web.config by the sitemap and Roles.IsUserInRole? Basically, I'm trying to prevent having the same permission descriptions in 435234 different places.

I attempted Casses solution to add embedded code in the sitemap file that would use settings from the web config - but that doesn't work (because you can't put embedded code in the sitemap file).

1

There are 1 best solutions below

11
On

Your examples don't actually define the same behaviour in 3 different ways. The first and third are similar, though done differently. They prevent a user from seeing the links. But, if the user knows the URL to go directly to the target, they can bypass the links and get there anyway.

That's where the second example you posted comes in. It prevents loading the page unless you're in the correct role.

If you don't care about showing the links to everywhere, the second example is all you need. Users will be able to see the element on the sitemap and the links on whatever pages they're on, but clicking them will not bring them to the admin page. Whether or not that's acceptable for your project is up to you.

If you want to hide the links and limit the amount of code you right to do so, I would recommend something like this:

<% if Roles.IsUserInRole(@"domain\Administrators") { %>
<a href="~/adminpage.aspx">Admin Page</a>
... any other links you want to limit to the admin role ...
<% } %>

That will at least keep the code to a minimum. The links won't even be added to the DOM unless the authenticated user is in that role, and if at a later date you need to change what role is being checked, you have to change it in fewer locations.

Either way, the web.config entry you gave should be included. You shouldn't assume that a malicious user doesn't know what your admin page is called. Especially when it's called adminpage.

EDIT

To reduce the duplication of the role name, try defining it in a section of the web.config and referencing it from there. You won't be able to do that for the locations tag, but you should be able to everywhere else.

ConfigurationManager.AppSettings["AdminRole"]

for example.

In the Sitemap, try

<siteMapNode url="~/adminpage.aspx" title="admin" roles="<% ConfigurationManager.AppSettings["AdminRole"]%>"/>