1

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).

Mike
  • 643
  • 3
  • 10

1 Answers1

-1

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"]%>"/>
Al Bechard
  • 147
  • 4
  • I understand that they don't define the same behavior. If they did, I wouldn't have needed all 3 steps :-). I'm trying to eliminate having hard coded roles all over the place. They are adequately defined in the Web.config - and I'd like to find a way to reuse them. – Mike Jul 26 '14 at 16:19
  • When you say they are well defined in your web.config, do you mean the location element you listed? – Al Bechard Jul 26 '14 at 16:24
  • Yes (mind you, in reality, there is more than one location element). My point is, role access to every page / directory is defined in location elements in the Web.config. There should be some way to utilize this from the sitemap, and from code. As it is now, if a group name changes, I have to change it in at least 2 places (web.config and web.sitemap) - and then anywhere it is used in code. – Mike Jul 26 '14 at 16:28
  • have you tried storing the role name elsewhere in the web.config, in a custom namevalue collection, and referencing that? The location elements aren't meant to be referenced in the fashion you're looking for. – Al Bechard Jul 26 '14 at 16:31
  • If I added something in appSettings like – Mike Jul 26 '14 at 16:36
  • I assumed you already were using security trimming. So if you're not, then yes, it would hide those links you're not able to view automatically. But, you do still need the roles attribute in your sitemapnode tag. Security trimming uses that attribute to determine whether or not to trim. As for the web.config bit, it looks like not. You might be able to do it if you write your own Location configuration handler. But I'm not sure at the moment how much extra work that would be. – Al Bechard Jul 26 '14 at 16:43
  • My mistake - you are correct, I am already using security trimming. It really seems odd to me that the correct/accepted way to handle this is to duplicate the same thing over and over again. I don't think this combination of functionality (config, sitemap, check user access) is all that uncommon. – Mike Jul 26 '14 at 16:50
  • You can define the role name in the web.config and use that everywhere except the location tag, most likely. The best I can do is help minimize the duplication. – Al Bechard Jul 26 '14 at 16:54
  • How would I use the key in the sitemap? – Mike Jul 26 '14 at 17:02
  • I added to my initial answer to explain that. – Al Bechard Jul 26 '14 at 17:05
  • I just tried that solution in the sitemap - but it doesn't work. I get an error "The XML sitemap config file Web.sitemap could not be loaded. '<' is an invalid attribute character." – Mike Jul 28 '14 at 12:15