ASP.net MVC中的自定义表单身份验证/授权方案

时间:2010-02-24 20:21:28

标签: asp.net asp.net-mvc security asp.net-mvc-2 authorization

我正在尝试使用表单身份验证在ASP.NET MVC中创建自定义身份验证方案。我可能在网站上有不同区域进行管理的想法 - 审批者是和一般用户区域,这些将使用不同的登录页面,依此类推。所以这就是我想要发生的事情。

  1. 用户访问受限页面(现在我用客户AuthorizeAttribute保护它)
  2. 用户被重定向到特定的登录页面(不是Web.config中的登录页面)。
  3. 验证用户凭据(通过自定义数据库方案)和用户登录。
  4. 真的很感激任何帮助!

    这就是我到目前为止所做的事情,它不起作用:

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

4 个答案:

答案 0 :(得分: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 :(得分:3)

好的,你去The Code

在那里你有ActionFilters文件夹(AuthAccess.cs) 插件文件夹(security.cs(加密/解密cookie),SessionHandler.cs(所有登录事项)) Controllers文件夹(BaseController.cs和exampleController(向您展示如何使用) 和loginTable SQL文件。

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

使用起来非常简单,可以暂时搁置一段时间,享受

nope cookie模型在这里抱歉:

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

答案 2 :(得分:2)

这不是角色的用途吗? 查看asp.net mvc authorization using roles或查看一般的角色

答案 3 :(得分:0)

在我有一个用于登录的课程

之前,我解决了这个问题

例程是登录,读取cookie,检查cookie,他们有一个包含

的模型

姓名,电子邮件,身份证,用户级别

然后你就拥有了自己的自定义actionFilter

例如[CustomAuth(MinAllowedLevel = 10)]

我为所有控制器使用基类,这样我就可以更轻松地链接到 所有我的会话内容,然后可以得到这样的信息

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

如果你想在英国白天回来的话,我会把代码发送到tommorow

说10小时我会让你有所有会话的课程和 您可以使用的自定义操作过滤器,然后您需要的是一个带有userlevel字段的登录表,最好是10,20,30,40的级别,如果您需要1到2之间的级别