【问题标题】:Custom form authentication / Authorization scheme in ASP.net MVCASP.net MVC 中的自定义表单身份验证/授权方案
【发布时间】:2011-01-20 17:08:33
【问题描述】:

我正在尝试使用表单身份验证在 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 };

        }
    }
}

【问题讨论】:

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


    【解决方案1】:

    我使用了 minus4 建议的代码和上面我自己的代码的组合来创建这个可能对其他人有帮助的简化场景。我添加了一些关于起初让我感到困惑的事情的 cmets。

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

    【讨论】:

    • 表单验证码很棒。但是需要注意的一件事是,我认为最好的做法是仅重定向到本地的 url。这减轻了重定向攻击的可能性。见:asp.net/mvc/tutorials/security/…
    【解决方案2】:

    好的,你去The Code

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

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

    使用起来真的很简单,会留给你一段时间,好好享受

    抱歉,没有 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; }
    }
    }
    

    【讨论】:

    • 非常感谢,代码帮助了。我做了一些更改以简化它并适合原始问题。
    • 这很酷,是为了成为一个乐于提供帮助的良好开端的基础
    【解决方案3】:

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

    【讨论】:

    • 嗯,不完全是,如果您在您的站点中有完全独立的登录区域,这些区域不应混合在一起,并且每个区域都需要不同的登录,那么您就不能使用角色。例如,如果您有网站的管理员选项(任何访问者都不应看到)以及使用该网站的客户帐户。当您在未登录的情况下点击安全页面时,它应该根据正在访问的区域将用户弹回不同的登录屏幕。
    【解决方案4】:

    在我有一个用于登录的课程之前,我已经解决了这个问题

    例程是登录、读取 cookie、检查 cookie,它们的模型包含

    姓名、电子邮件、ID、用户级别

    那么你就拥有了自己的自定义 actionFilter

    例如 [CustomAuth(MinAllowedLevel=10)]

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

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

    如果你想要的话,我明天会在我回到英国白天时为你提供代码

    说 10 小时后,我会让你参加所有会议内容的课程和 您可以使用自定义操作过滤器,那么您只需要一个带有用户级别字段的登录表,最好使用 10、20、30、40 级别,以防您需要介于 1 和 2 之间的级别

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      相关资源
      最近更新 更多