在我的Asp.NET C#应用程序中,我有一个绑定到菜单的站点地图,用于站点导航。为了控制用户访问,我使用Manuel Abadia的NHibernate自定义角色提供程序,并在每个SiteMap节点上设置"角色"属性。
<siteMapNode title="Add/Modify Roles" description="Add/Modify User Roles"
url="~/MemberPages/Admin_Roles.aspx" roles="Administrator" />
到目前为止,一切都很好,但现在我希望有几个网页不出现在站点地图绑定菜单上,但仍然使用站点地图节点来控制用户访问。例如,我有一个专门用于管理员的页面,它显示数据库中的所有角色(ViewPage)。在该页面上,我有一个"添加新角色"按钮,它将用户重定向到另一个页面以添加新角色(AddPage)。ViewPage应该存在于菜单上,AddPage不应该存在,但两者应该共享相同的访问设置(只有管理员才能访问)。
我应该如何实现这一点?我知道我可以在web.config文件中声明访问设置,但我宁愿避免这样做,因为会有很多像这样的页面。此外,系统管理员将被允许自定义访问规则,比如将其从仅管理员更改为管理员;因此,如果系统可以更改一个网站地图中所有页面的访问规则,会更方便。
感谢MikeSmithDev的评论,我终于找到了一个不错的解决方案。如果其他人遇到同样的问题,我会这样做:
在我的SiteMap中,我添加了一个自定义属性HideFromMenu
:
<siteMapNode title="Add Page" description="Page to Add stuff"
roles="Administrator" url="~/AddPage.aspx" HideFromMenu="true" />
在我的菜单控件中,我添加了OnMenuItemDataBound
属性:
<asp:Menu ID="Menu1" runat="server" DataSourceID="siteMapSource"
OnMenuItemDataBound="Menu1_MenuItemDataBound" >
在大师的代码后面:
protected void Menu1_MenuItemDataBound(object sender, MenuEventArgs e)
{
SiteMapNode node = (SiteMapNode)e.Item.DataItem;
if (node["HideFromMenu"] == "true")
{
if (e.Item.Parent != null) //if this item has a parent..
e.Item.Parent.ChildItems.Remove(e.Item); //use parent to remove child..
else
Menu1.Items.Remove(e.Item); //else.. remove from menu itself.
}
}
最后,为了确保用户不会越界访问页面,我在主页面中添加了一些验证。。
var authorizedRoles = SiteMap.CurrentNode.Roles; //obtain the list of authorized roles for the current page
if (authorizedRoles == null || authorizedRoles.Count == 0) // no roles defined for this node
isAuthorized = false;
else
{
if (authorizedRoles.Contains("*")) // this page can be accessed by everyone
isAuthorized = true;
if (!isAuthorized)
{
foreach (string authorizedRoleName in authorizedRoles)
{
if (Roles.IsUserInRole(authorizedRoleName) == true)
{
isAuthorized = true;
break;
}
}
}
}
if (!isAuthorized)
Response.End(); // unauthorised user; kill the page.
我希望这能帮助任何面临同样问题的人。如果有更好的方法可以达到同样的效果,请告诉我。