ASP.NET MVC中用户授权/身份验证的最佳方法是什么?
我看到有两种方法:
使用内置的ASP.NET授权系统.
使用具有我自己的用户,权限,用户组表等的自定义系统.
我更喜欢第二个选项,因为User是我的域模型的一部分(我对ASP.NET内置的东西没有经验),但我真的很想听听人们在这个领域做过什么.
实际上有第三种方法.asp.net成员资格功能基于提供者模型.您可以编写自定义提供程序,从而能够提供自己的数据存储方式,但保留了asp.net成员资格的许多好处.
关于这个主题的一些文章:
http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
http://www.asp.net/learn/videos/video-189.aspx
http://www.15seconds.com/issue/050216.htm
http://davidhayden.com/blog/dave/archive/2007/10/11/CreateCustomMembershipProviderASPNETWebsiteSecurity.aspx
去定制.MembershipProvider对我的口味来说太沉重了.是的,它可以以简化的方式实现它,但是你会得到一个非常难闻的NotSupportedException或NotImplementedException.
通过完全自定义的实现,您仍然可以使用IPrincipal,IIdentity和FormsAuth.你自己的登录页面真的有多难?
最简单的方法是使用asp.net用户名作为角色名称.您可以编写自己的authorizarion属性来处理授权:
public class CustomAuthorizationAttribute:AuthorizeAttribute { public CustomAuthorizationAttribute():base() { Users = "registereduser"; } protected override bool AuthorizeCore(HttpContextBase httpContext) { //You must check if the user has logged in and return true if he did that. return (bool)(httpContext.Session["started"]??false); } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { filterContext.HttpContext.Response.Redirect("SessionManagement/Index/?returningURL=" + filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.Url.ToString())); } }
代码必须处理AuthorizeCore以在用户启动会话时返回true,并且HandleUnauthorizedRequest将用户重定向到登录页面(可选地,您可以附加返回的URL).
在那些需要授权的控制器方法中,将属性设置在它们上面:
public class SecretPageController { [CustomAuthorizationAttribute] ActionResult Index() { //Method that requires authorization return View(); } }
还要在Web配置中将授权方法设置为"Forms".
Web.config文件:
控制器:
public SessionManagementController:Controller { public ActionResult Index(string returningURL) { return View("Index", new SessionModel() { ReturningURL = returningURL}); } [HttpPost] public ActionResult Index(SessionModel mod) { if (UserAuthenticated(mod.UserName, mod.Password)) { FormsAuthentication.SetAuthCookie("registereduser", false); if (mod.UrlRetorno != null) { return Redirect(mod.ReturningURL); } return RedirectToAction("Index", "StartPage"); } mod.Error = "Wrong User Name or Password"; return View(mod); } bool UserAuthenticated(string userName, string password) { //Write here the authentication code (it can be from a database, predefined users,, etc) return true; } public ActionResult FinishSession() { HttpContext.Session.Clear();//Clear the session information FormsAuthentication.SignOut(); return View(new NotificacionModel() { Message = "Session Finished", URL = Request.Url.ToString() }); } }
在Controller中,当用户输入其用户名和密码时,将表单身份验证cookie设置为TRUE(FormsAuthentication.SetAuthCookie("registereduser",true)),指示要进行身份验证的用户名(示例中的registereduser).然后用户注销,告诉ASP.NET这样做,调用FormsAuthentication.SignOut().
模型:
class SessionModel { public string UserName {get;set;} public string Password {get;set;} public string Error {get;set;} }
使用模型存储用户数据.
View(显示SessionModel类型):
<%: Html.LabelFor(model => model.UserName) %><%: Html.TextBoxFor(model => model.UserName) %> <%: Html.ValidationMessageFor(model => model.UserName) %><%: Html.LabelFor(model => model.Password) %><%: Html.TextBoxFor(model => model.Password) %> <%: Html.ValidationMessageFor(model => model.Password) %><%:Model==null?"":Model.Error??"" %><%:Html.HiddenFor(model=>model.ReturningURL) %>
使用视图获取数据.在此示例中,有一个隐藏字段用于存储返回的URL
我希望这有帮助(我必须翻译代码,所以我不确定它是否100%正确).
另一种方法是使用ASP.NET成员身份进行身份验证,将User类链接到ASP.NET成员,并使用User类获得更细粒度的权限.我们这样做,因为它允许非常容易地更改身份验证提供程序,同时仍然保留具有复杂权限系统的能力.
一般来说,值得记住的是,身份验证/身份和存储权限不一定是同一个问题.