在Web应用开发中,身份验证是一个重要的环节,它确保了只有授权用户才能访问敏感资源。本文将介绍如何使用表单验证来控制对特定文件夹的访问权限,特别是如何仅允许具有管理员角色的用户访问特定资源。
在开发网站时,经常需要对不同用户设置不同的访问权限。例如,普通用户只能浏览网站,而注册用户可以执行一些操作,如添加或删除内容。对于具有管理员角色的用户,希望他们能够访问更多的资源,如管理文件夹。本文将探讨如何实现这种基于角色的访问控制。
首先,需要下载并解压示例代码,然后在IIS中为其创建一个虚拟目录。根目录包含登录页面(login.aspx)、登出页面(logout.aspx)、首页(default.aspx)以及一个名为“admin”的文件夹。在“admin”文件夹中,放置了一个名为default.aspx的文件,这是希望阻止普通用户访问的文件。
在web.config文件中,需要设置身份验证模式为“Forms”,并定义一个特定于“Admin”文件夹的授权规则,如下所示:
<location path="Admin">
<system.web>
<authorization>
<allow roles="Administrators" />
<deny users="*" />
</authorization>
</system.web>
</location>
<authentication mode="Forms">
<forms name="AuthCookie" path="/" loginUrl="login.aspx" protection="All" timeout="30">
</forms>
</authentication>
请确保将<allow roles="Administrators" />放在<deny users="*" />之前,否则没有人能够访问“admin”文件夹。
为了使网站更易于维护,使用web.sitemap文件来定义网站结构。在web.sitemap文件中,创建了几个SiteMapNode,并将“Administrators”角色分配给相应的节点,如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
<siteMapNode url="~" title="Home" description="">
<siteMapNode url="default.aspx" title="Home" description="" roles="*" />
<siteMapNode url="login.aspx" title="Login" description="" roles="*" />
<siteMapNode url="Admin/" title="Administration" description="">
<siteMapNode url="Admin/default.aspx" title="Administration" description="" roles="Administrators" />
</siteMapNode>
<siteMapNode url="logout.aspx" title="Logout" description="" roles="*" />
</siteMapNode>
</siteMap>
当用户首次访问网站时,他们可以看到“Administration”超链接。点击该链接后,由于web.config文件的设置,IIS的FormsAuthentication对象会将用户重定向到login.aspx页面,要求用户登录。用户输入用户名和密码后,通过数据库访问等多种方法进行验证。验证成功后,为特定用户分配“Administrators”角色,如下所示:
FormsAuthenticationUtil.RedirectFromLoginPage("Lewis", "Administrators", true);
FormsAuthenticationUtil是一个第三方DLL,它为用户创建一个身份验证票据,并将用户的登录状态更改为“已登录”。后来,停止使用这个DLL,因为需要完全控制用户的登录过程。
创建了一个用户类,专门处理用户的登录和注册过程等。以下是代码片段:
public static void CreateTicket(ENetUser newUser, bool persistantCookie)
{
string roles = "users";
if (newUser.Email.ToLower().Trim() == "abc@hotmail.com" ||
newUser.Email.ToLower().Trim() == "john.dole@pertronic.co.nz")
roles = "Administrators";
roles += "," + newUser.ID;
roles += "," + newUser.ID;
// 创建一个新的票据用于身份验证
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
newUser.UserName,
DateTime.Now,
DateTime.Now.AddMinutes(30),
persistantCookie,
roles,
FormsAuthentication.FormsCookiePath);
// 加密cookie以安全传输
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
hash);
if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
}
如上所示,为用户创建了一个票据,并在用户的PC上添加了一个cookie。当用户下次访问网站时,从该Cookie重新创建用户的票据。
需要告诉Web应用程序如何验证用户。在global.asax文件中添加了以下代码行,如果Web根目录中没有该文件,请通过选择Visual Studio 2008的“添加新项”从“Web站点”菜单中添加它。
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
}
如上所示,一旦用户登录,他们将被认证,但他们还没有“Administrators”角色。使用上述例程为用户分配该角色。
在网站上,在global.asax文件中添加了以下代码,在会话开始时读取cookie,为用户提供票据,应用程序认证方法将使用该票据授予用户“administrators”角色。
void Session_Start(object sender, EventArgs e)
{
HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
}
}