Asp.net

ASP.net MVC 中的自定義表單身份驗證/授權方案

  • July 23, 2010

我正在嘗試使用表單身份驗證在 ASP.NET MVC 中創建自定義身份驗證方案。我可能在網站上有不同的區域進行管理 - 批准者和一般使用者區域,這些將使用不同的登錄頁面,等等。所以這就是我想要發生的事情。

  1. 使用者訪問受限頁面(現在我用客戶 AuthorizeAttribute 保護它)
  2. 使用者被重定向到一個特定的登錄頁面(不是來自 Web.config 的那個)。
  3. 驗證使用者憑據(通過自定義數據庫方案)和使用者登錄。

非常感謝任何幫助!

這就是我到目前為止所擁有的,但它不起作用:

public class AdministratorAccountController : Controller
{
   public ActionResult Login()
   {
       return View("Login");
   }

   [HttpPost]
   public ActionResult Login(AdministratorAccountModels.LoginModel model, string returnUrl)
   {
       if (ModelState.IsValid)
           if (model.UserName == "admin" && model.Password == "pass") // This will be pulled from DB etc
           {
               var ticket = new FormsAuthenticationTicket(1,               // version 
                                                          model.UserName,  // user name
                                                          DateTime.Now,    // create time
                                                          DateTime.Now.AddSeconds(30), // expire time
                                                          false,           // persistent
                                                          "");             // user data

               var strEncryptedTicket = FormsAuthentication.Encrypt(ticket);
               var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strEncryptedTicket);
               Response.Cookies.Add(cookie);

               if (!String.IsNullOrEmpty(returnUrl))
               {
                   return Redirect(returnUrl);
               }
               else
               {
                   return RedirectToAction("Index", "Home");
               }
           }
           else
           {
               ModelState.AddModelError("", "The user name or password provided is incorrect.");
           }

       // If we got this far, something failed, redisplay form
       return View(model);
   }

   [AdministratorAuthorize]
   public ActionResult MainMenu()
   {
       return View();
   }

   public class AdministratorAuthorizeAttribute : AuthorizeAttribute
   {
       protected override bool AuthorizeCore(HttpContextBase httpContext)
       {
           var authenCookie = httpContext.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
           if (authenCookie == null) return false;

           var ticket = FormsAuthentication.Decrypt(authenCookie.Value);
           var id = new FormsIdentity(ticket);
           var astrRoles = ticket.UserData.Split(new[] { ',' });
           var principal = new GenericPrincipal(id, astrRoles);
           httpContext.User = principal;
           return true;
       }

       protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
       {
           var model = new AdministratorAccountModels.LoginModel();
           var viewData = new ViewDataDictionary(model);

           filterContext.Result = new ViewResult { ViewName = "Login", ViewData = viewData };

       }
   }
}

我使用了 minus4 建議的程式碼和上面我自己的程式碼的組合來創建這個可能對其他人有幫助的簡化場景。我添加了一些關於起初讓我感到困惑的事情的評論。

public class AdministratorAccountController : Controller
{
   public ActionResult Login()
   {
       return View("Login");
   }

   [HttpPost]
   public ActionResult Login(AdministratorAccountModels.LoginModel model, string returnUrl)
   {
       if (ModelState.IsValid)
           // Here you would call a service to process your authentication
           if (model.UserName == "admin" && model.Password == "pass")
           {
               // * !!! *
               // Creating a FromsAuthenticationTicket is what 
               // will set RequestContext.HttpContext.Request.IsAuthenticated to True
               // in the AdminAuthorize attribute code below
               // * !!! *
               var ticket = new FormsAuthenticationTicket(1, // version 
                                                          model.UserName, // user name
                                                          DateTime.Now, // create time
                                                          DateTime.Now.AddSeconds(30), // expire time
                                                          false, // persistent
                                                          ""); // user data, such as roles

               var strEncryptedTicket = FormsAuthentication.Encrypt(ticket);
               var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, strEncryptedTicket);
               Response.Cookies.Add(cookie);

               // Redirect back to the page you were trying to access
               if (!String.IsNullOrEmpty(returnUrl))
               {
                   return Redirect(returnUrl);
               }
               else
               {
                   return RedirectToAction("Index", "Home");
               }
           }
           else
           {
               ModelState.AddModelError("", "The user name or password provided is incorrect.");
           }

       // If we got this far, something failed, redisplay form
       return View(model);
   }

   [AdminAuthorize]
   public ActionResult MainMenu()
   {
       return View();
   }

   public class AdminAuthorize : ActionFilterAttribute
   {
       public override void OnActionExecuting(ActionExecutingContext filterContext)
       {
           if (!filterContext.RequestContext.HttpContext.Request.IsAuthenticated)
           {
               // Redirect to the needed login page
               // This can be pulled from config file or anything else
               filterContext.HttpContext.Response.Redirect("/AdministratorAccount/Login?ReturnUrl=" 
                                       + HttpUtility.UrlEncode(filterContext.HttpContext.Request.RawUrl));               
           }

           base.OnActionExecuting(filterContext);
       }
   }
}

引用自:https://stackoverflow.com/questions/2329197