[原文源码下载]
[翻译]开发自己的web站点管理工具(Website Administration Tool)(2)
原文发布日期:2007.05.30
作者:Dan Clem
翻译:webabcd
介绍
为了方便管理用户、角色和权限设置,ASP.NET 2.0内置了Web Site Administration Tool (WSAT),你可以在Visual Studio 2005的“网站”菜单下选择“ASP.NET 配置”来启动WSAT。 但是,WSAT只允许你管理本地的web站点。 当web站点部署在远程web主机上的时候,WSAT就会受到一些限制。 所以,我决定从零开始开发一个自己的WSAT程序。本系列文章的第一部分从整体上讲述了我的自定义WSAT程序的实现,并且讲解了其中关于用户管理的部分。
本文是该系列文章的第二部分,也是最后一部分,在这里我会详细讲解上一篇文章中没有说明的一些要点: 角色管理和访问规则管理。 你可以在本文的结尾处下载我写的WSAT程序的全部代码。 关于如何在一个新建或已有的web程序中使用我的这个WSAT程序,你可以参考本系列文章的第一部分(译者注:中文在这里)中的“使用我的自定义web站点管理工具(WSAT)”。 继续往下看,你会学到更多的在我的自定义WSAT程序中关于角色管理和访问规则管理的相关知识。
你最好已经看过本系列文章的第一部分
在看本文之前,你最好已经阅读过本系列文章的第一部分(译者注:中文在这里)。在第一部分中,我从整体上讲述了我的自定义WSAT程序的实现,并且一步一步地说明了如何在一个新建或已有的web程序中使用我的这个WSAT程序,另外,如何实现管理用户的功能我也做了充分的讲解。 你可以在本文结尾处或本系列文章的第一部分的结尾处下载这个自定义的WSAT程序的全部代码。
角色管理
我的自定义WSAT程序的角色管理部分完成了如下3个任务:
·显示系统内的所有角色
·允许删除一个已存在的角色
·允许新建角色
我把实现这3个任务的功能恰当地放到了一个web页面内,其截屏如下:
我使用了一个GridView来显示所有角色。 Roles类的GetAllRoles方法返回的是系统内的角色名数组(字符串数组)。 除了列出所有角色外,我还想显示出每一个角色所关联的用户的数量。 所以,直接通过GetAllRoles方法返回一个字符串数组绑定给GridView满足不了我的需求,于是我决定构造一个自己的DataTable,并使其作为GridView的数据源。 我把这段代码写到了Page_PreRender方法内。
// 新建一个DataTable,并定义它的列
DataTable RoleList = new DataTable();
RoleList.Columns.Add("Role Name");
RoleList.Columns.Add("User Count");
// 获取角色列表和每一个角色下的用户数
string[] allRoles = Roles.GetAllRoles();
foreach (string roleName in allRoles)
{
int numberOfUsersInRole = Roles.GetUsersInRole(roleName).Length;
string[] roleRow = { roleName, numberOfUsersInRole.ToString() };
RoleList.Rows.Add(roleRow);
}
// 绑定DataTable给GridView
UserRoles.DataSource = RoleList;
UserRoles.DataBind();
DataTable RoleList = new DataTable();
RoleList.Columns.Add("Role Name");
RoleList.Columns.Add("User Count");
// 获取角色列表和每一个角色下的用户数
string[] allRoles = Roles.GetAllRoles();
foreach (string roleName in allRoles)
{
int numberOfUsersInRole = Roles.GetUsersInRole(roleName).Length;
string[] roleRow = { roleName, numberOfUsersInRole.ToString() };
RoleList.Rows.Add(roleRow);
}
// 绑定DataTable给GridView
UserRoles.DataSource = RoleList;
UserRoles.DataBind();
向系统内添加一个新的角色,只需要下面这样的一行代码:
Roles.CreateRole(roleName);
同样,删除一个角色也只需要一行代码:
Roles.DeleteRole(roleName);
需要注意的是,如果一个角色内有一个或更多的用户,那么这时你要删除这个角色的话,默认的Provider就会抛出一个异常。 所以,在删除一个角色的时候要先移出角色内的所有成员。你可以调用Roles类的RemoveUsersFromRole方法来做这项工作。 该方法需要两个参数: 角色内需要移除的成员的用户名数组和角色名称。 你可以使用GetUsersInRole方法来得到指定角色下的所有用户(返回的是一个包含用户名称的字符串数组)。
访问规则管理
在“访问规则管理”页中,使用了一个TreeView控件来显示web程序内的目录(文件夹)结构列表。 树型结构的显示是通过Page_Load事件调用的PopulateTree()方法内的代码实现的。 (我从Scott Mitchell的文章Using the TreeView Control and a DataList to Create an Online Image Gallery中几乎是一个字一个字地复制了PopulateTree方法和AddNodeAndDescendents方法)
要使用“访问规则管理”这个功能的话,你需要以隶属于管理员角色的用户登录。 在详细讲解之前,我们先来看看.net自带的WSAT程序中总结的一句话: “规则按顺序应用。应用符合条件的第一个规则,每个规则中的权限重写其后所有规则中的权限。”
访问规则的设置保存在每一个文件夹中的Web.config文件内。 你可以手写这些Web.config文件,也可以使用WebConfigurationManager类对访问规则进行管理。 注意一下你的ASP.NET程序是在Windows的哪个用户之下运行的,一般来说应该是 NT Authority\Network Service用户,你必须要保证这个用户有读写Web.config文件的权限。
在“访问规则管理”页中,管理员角色的用户可以通过单击左侧的目录树视图,来管理指定文件夹的访问规则。 你可以对访问规则进行添加、移动或删除的操作。 子文件夹的访问规则会继承其父文件夹,但是不可以在子文件夹中更改在父文件夹中制定的访问规则。 你可以通过指定用户或角色的Deny和Allow行为来创建新的访问规则。 我的这个WSAT程序可以设置你所选择的用户或角色的权限, 也可以指定所有用户(*)或匿名用户(?)的权限。
添加规则分两步走: 首先新建一个规则,然后将其添加到web配置中。
// 新建规则
AuthorizationRule newRule;
if (ActionAllow.Checked) newRule = new AuthorizationRule(AuthorizationRuleAction.Allow);
else
newRule = new AuthorizationRule(AuthorizationRuleAction.Deny);
// 添加规则
if (ApplyRole.Checked && UserRoles.SelectedIndex > 0)
{
newRule.Roles.Add(UserRoles.Text);
AddRule(newRule);
}
else if (ApplyUser.Checked && UserList.SelectedIndex > 0)
{
newRule.Users.Add(UserList.Text);
AddRule(newRule);
}
else if (ApplyAllUsers.Checked)
{
newRule.Users.Add("*");
AddRule(newRule);
}
else if (ApplyAnonUser.Checked)
{
newRule.Users.Add("?");
AddRule(newRule);
}
AuthorizationRule newRule;
if (ActionAllow.Checked) newRule = new AuthorizationRule(AuthorizationRuleAction.Allow);
else
newRule = new AuthorizationRule(AuthorizationRuleAction.Deny);
// 添加规则
if (ApplyRole.Checked && UserRoles.SelectedIndex > 0)
{
newRule.Roles.Add(UserRoles.Text);
AddRule(newRule);
}
else if (ApplyUser.Checked && UserList.SelectedIndex > 0)
{
newRule.Users.Add(UserList.Text);
AddRule(newRule);
}
else if (ApplyAllUsers.Checked)
{
newRule.Users.Add("*");
AddRule(newRule);
}
else if (ApplyAnonUser.Checked)
{
newRule.Users.Add("?");
AddRule(newRule);
}
AddRule方法用于访问指定文件夹的配置文件,并添加我们的权限规则。
private void AddRule(AuthorizationRule newRule)
{
string virtualFolderPath = FolderTree.SelectedValue;
Configuration config = WebConfigurationManager.OpenWebConfiguration(virtualFolderPath);
SystemWebSectionGroup systemWeb = (SystemWebSectionGroup)config.GetSectionGroup("system.web");
AuthorizationSection section = (AuthorizationSection)systemWeb.Sections["authorization"];
section.Rules.Add(newRule);
try
{
config.Save();
RuleCreationError.Visible = false;
}
catch (Exception ex)
{
RuleCreationError.Visible = true;
RuleCreationError.Text = "<div class=\"alert\">An error occurred and the rule was not added.<i>" + ex.Message + "</i></div>";
}
}
{
string virtualFolderPath = FolderTree.SelectedValue;
Configuration config = WebConfigurationManager.OpenWebConfiguration(virtualFolderPath);
SystemWebSectionGroup systemWeb = (SystemWebSectionGroup)config.GetSectionGroup("system.web");
AuthorizationSection section = (AuthorizationSection)systemWeb.Sections["authorization"];
section.Rules.Add(newRule);
try
{
config.Save();
RuleCreationError.Visible = false;
}
catch (Exception ex)
{
RuleCreationError.Visible = true;
RuleCreationError.Text = "<div class=\"alert\">An error occurred and the rule was not added.<i>" + ex.Message + "</i></div>";
}
}
向上或向下移动规则需要我们自己来手写更多的代码,因为.net没有提供内置的方法来实现这个功能。 我用的方法是通过一个数组来排序各个规则,从而完成这项工作。 我认为这个方法还是比较简单的,所以就不详细说明了,其主要就是先从配置文件中读出所有规则并放到一个ArrayList对象中,同时再删除配置文件中的所有规则,然后根据用户的需要对这个数组进行排序,最后再将排序好的规则重新写人配置文件中。
“访问规则摘要”页的实现方法
让我们开发我们自已的“访问规则摘要”页吧,在.net内置的WSAT程序中是没有这个功能的。 隶属于管理员角色的用户可以在这个页中查看指定的角色或用户在各个目录中的权限。
在这个页中,角色和用户的选择是通过DropDownList控件实现的。 当你选择了一个角色或用户之后,TreeView控件就会列出web程序内的所有文件夹。 它与“访问规则管理”页中的TreeView控件比较相似,所不同的就是这个TreeView控件用红色和绿色标记来表示你所选择的角色或用户在某目录中的权限。 当然就像你认为的那样,绿色代表你所选择的角色或用户有访问的权限,红色则正好相反。 除了红色和绿色标记之外,TreeView控件上的文本还会显示出为什么你所选择的角色或用户会有这样的权限。 通过下面的截屏你就可以发现,被选中的用户为“Franklin Forester”,因为他属于“Marketing”角色,所以有对marketing文件夹的访问权限。
让我们的自定义WSAT程序安全地运行
现在我们就可以把这个自定义WSAT程序移植到我们的新建或已有的web站点里,为了保证程序的安全,我们希望只有管理员才能访问它。 为了实现这个功能,需要增加两个访问规则。 在我的例子中,我只允许管理员角色有对admin文件夹的访问权限,然后拒绝其他所有用户,如下图所。 注意,允许管理员角色访问的规则必须在拒绝所有用户访问的规则的上面,否则将不会有任何人有权限访问这个文件夹。(如果你不小心使得管理员角色无法访问admin文件夹的话, 那么你就需要手动修改Web.config文件,以使管理员角色可以访问你的自定义WSAT程序的admin文件夹。)
结论
虽然可以通过ASP.NET 2.0内置的web站点管理工具(WSAT)来管理用户、角色和权限,但是该工具只能在本地使用,而且有一些功能上的不足。 所以本文和本系列文章的第一部分(译者注:中文在这里)探讨了如何实现一个自定义的WSAT程序。 这个自定义WSAT程序可以移植到你的新建或已有的 ASP.NET web程序中,并且可以部署在远程服务器。 此外,为了改进原来的WSAT程序,它还附加了一些新的特性。
祝编程愉快!