2010-02-24 53 views
8

我想在ASP.NET MVC中使用窗体身份验证创建一个自定义身份验证方案。我可能会在网站上有不同的区域,即将被管理的想法 - 审批者和一般用户区域,这些区域将使用不同的登录页面,等等。所以这就是我想要发生的事情。ASP.net中的自定义窗体身份验证/授权方案MVC

  1. 用户访问受限制的网页(现在我已经将其与客户AuthorizeAttribute保护)
  2. 用户被重定向到一个特定的登录页面(而不是一个从Web.config文件)。
  3. 用户凭据进行验证(通过自定义DATABSE方案)和用户登录。

会很感激的任何帮助!

这是我我有什么,到目前为止,这是行不通的:

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 }; 

     } 
    } 
} 

回答

15

我使用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); 
     } 
    } 
} 
+1

形式认证代码是伟大的。但有一点要注意,我认为最好的做法是只在本地重定向到url。这减轻了重定向攻击的可能性。请参阅:http://www.asp.net/mvc/tutorials/security/preventing-open-redirection-attacks – 2012-11-02 21:27:57

0

我解决了这个人之前我有一个类我使用的登录

程序是登录,阅读饼干,饼干检查,他们有一个包含

姓名,电子邮件,身份证的模型,用户级

,那么你只需要自己的自定义actionFilter

如[CustomAuth(MinAllowedLevel = 10)]

我用我所有的控制器里继承,所以我可以有一个更容易链接到 我所有的会话内容,然后可以得到的信息,像这样

var model = pictures.all().where(x => x.userid == users.ReadCookie.userID) 

我会了上来代码明天,如果你想为你的时候,我回来在英国白天

说10个小时,我将让你拥有类的所有会话的东西,你可以使用 自定义操作过滤器,那么你所需要的只是一个登录s用户级别的表格,最好的级别为10,20,30,40级别需要级别在1和2之间

+0

谢谢,期待看到代码! – 2010-02-24 23:56:47

2

这不是什么作用? 看一看asp.net mvc authorization using roles或者一般看看角色

+1

好吧,不完全是这样的,如果您的站点中有完全独立的日志记录区域,不应该混合在一起并且每个日志都需要不同的登录名称,则不能使用角色。 例如,如果您拥有网站的管理员选项(任何访客都不应该看到该选项)以及使用该网站的客户帐户。当您在未登录的情况下点击安全页面时,它会根据正在访问的区域将用户弹回到不同的登录屏幕。 – 2010-02-25 15:03:50

+0

感谢您的澄清... – spaceman 2010-02-26 06:11:44

3

还好在这里你去The Code

在那里你ActionFilters文件夹(AuthAccess.cs) plugins文件夹中(security.cs(加密/解密的cookie ),SessionHandler.cs(登录)) 控制器文件夹(BaseController.cs的所有事项,并exampleController(告诉你如何使用) 和loginTable SQL文件。

我用mysql,所以你可能需要修改,我也使用亚音速,所以我的模型将来自 并且会在空模型文件夹中。

非常简单的使用会离开它了一段时间的你,享受

没了饼干模型是在这里遗憾:

using System; 

namespace TestApp.Models 
{ 
    public class CookieModel 
{ 
    public string CurrentGuid { get; set; } 
    public DateTime LoginTime { get; set; } 
    public Int32 UserLevel { get; set; } 
    public Int32 LoginID { get; set; } 
    public bool isValidLogin { get; set; } 
    public string realUserName { get; set; } 
    public string emailAddress { get; set; } 
} 
} 
+0

非常感谢,代码帮助。我做了一些改变,以简化它,并符合原来的问题。 – 2010-02-25 18:22:58

+0

多数民众赞成在酷意味着作为一个良好的开端的基础乐于帮助 – davethecoder 2010-02-25 19:16:09

+0

哪里是代码?链接没有它 – mamu 2010-12-24 04:23:44