议题
创建用户必须注册并通过用户名和密码登录才能访问的网站的特定页面。
创建具有权限控制的特定页面,用户必须通过注册并使用用户名和密码登录才能访问。
解决方案
AccountController和AccountModels以及几个验证视图通过Membership和FormsAuthentication来实现创建和验证用户的功能。在ASP.NET中通过AuthorizeAttribute控制访问权限。
讨论
微软的ASP.NET MVC团队针对AccountController做出很多改进,更新了FormsAuthentication类,通过Membership对象创建新用户、验证现有的用户创建Cookie并通过这个对象来检查用户状态。
与MVC 2不同,在第三版中,更新了“新建项目”的对话框,提供三种不同应用程序类型:空应用程序,互联网应用程序,内网应用程序。一个空的应用程序只在项目中创建 MVC所必须的文件夹结构。Internet应用程序,设置默认的模板,将创建和预配置的几个功能,包括一个基本的布局模板,以及通过AccountController进行用户注册、登录的MVC的应用程序。第三个模板是Intranet应用程序,与Internet应用程序不同,并没有使用Membership类进行验证而是使用Windows身份验证方式。
对大多数网站来说,使用默认的Internet应用程序即可。创建一个新的MVC3的Internet应用,将会产生AccountController、AccountModels和几个关于用户账号的视图,包含关于用户注册、登录、修改密码的视图。
为了防止用户访问某些页面,MVC在一些特定的Controller和Action上通过AuthorizeAttribute来控制访问。打开AcctionController.cs 我们会看到以下内容:
//
// GET: /Account/ChangePassword
[Authorize]
public ActionResult ChangePassword()
{
return View();
}
当未注册用户通过 /Account/ChangePassword 来访问的时候,MVC是自动跳转到登录页面。如果他们已经登录,就不会重定向页面,而会显示视图内容。默认重定向的用户登录地址可以在Web.Config文件中设置:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
假如用户之前从未注册过,最后将转入注册页面。默认注册时需要收集以下信息:
l 登录用户名
l 电子邮件地址
l 登录密码
AccountController中的Register方法通过Membership来创建新的用户账户。Register方法的输入参数为RegisterModel类型对象。针对页面的注册表单,我们在AccountModels定义了一个名为RegisterModel的对象。
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// 尝试注册用户
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password
, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false );
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
}
上面自动生成的代码,实现了三个重要功能:
- 用户输入数据之后通过Membership.CreateUser()方法创建一个新的用户;
- 确保用户已经创建成功,就通过FormsAuthentication.SetAuthCookie设置用户登录状态以便用户在以后页面访问时验证。
- 如果用户已经创建成功,用户就会被重定向回主页。(如果创建用户时出现错误,错误消息传递给错误视图,并将显示错误信息展示给用户)。
如果你已经安装完整版本的Visual Studio,就可以通过已安装的SQL Express创建数据库。或者,只安装基础版本的Visual Studio,也可以从微软的网站上面下载到免费的SQL Express。
在App_Data文件夹中创建的SQL Express数据库,系统会在web.config中添加默认数据库链接字符串。这个SQL Express数据库将包含Membership类需要存储的用户内容的各种表,例如用户资料、角色等。
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;
Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
当用户再次访问网站,上次通过FromsAuthentication设置的Cookie的依然有效(可能因为他们在登录的时候选中了“记住我”的选项或有其他正在浏览页面没有关闭),这时查看的视图并不会要求他们再次登录或注册。如果Cookie不存在,且用户已经完成注册,页面将会被重定向到登录页面。一旦用户输入登录信息并提交,AccountController将再次通过Memership验证用户登录。代码如下所示:
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName,
model.Password))
{
FormsAuthentication.SetAuthCookie(
model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl)
&& returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "提供的用户名或密码不正确。");
}
}
// 如果我们进行到这一步时某个地方出错,则重新显示表单
return View(model);
}
上面自动生成的代码,实现了三个重要功能:
- 通过Memership.ValidateUser()方法验证用户输入的用户名以及密码;
- 如果登录成功,将通过FormsAuthentication.SetAuthCookie方法设置登录信息;
- 假如用户通过验证,用户将被重定向至首页(或者他们没有通过验证,将会在页面中显示错误信息给用户)。
AuthorizeAttribute除了可以限制某些用户访问特定的页面,还可以提供其他限制选项。使用方法如下:
// Retrieve a list of all users to allow an admin
// to manage them
[Authorize(Roles = "Admin")]
public ActionResult UserAdmin()
{
MembershipUserCollection users =
Membership.GetAllUsers();
return View(users);
}
// Create some custom reports for me only
[Authorize(Users = "Jamie")]
public ActionResult JamieAdmin()
{
// Perform some logic to generate usage reports
...
return View();
}
这些简单的例子只是介绍了一些关于限制访问的入门内容。接下来的章节,我们将会研究添加自定义组访问限制Controller的方法。
参考信息