Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC表单身份验证多个同时登录_C#_Asp.net Mvc_Forms Authentication - Fatal编程技术网

C# ASP.NET MVC表单身份验证多个同时登录

C# ASP.NET MVC表单身份验证多个同时登录,c#,asp.net-mvc,forms-authentication,C#,Asp.net Mvc,Forms Authentication,我的情况可能与大多数情况相反,我希望允许多个同时登录,但仅限于不同类型的用户 用户-有自己的区域 管理员-有自己的区域 当管理员也可以是用户(他们有两个帐户,这主要是为了他们可以从用户PoV检查系统如何工作)并希望同时登录这两个帐户时,就会出现问题 对于表单身份验证,这似乎是不可能的。因此,我不得不稍微“破解”一下,担心自己可能忽略了一些东西 计划: 针对每种用户类型的两个操作筛选器:UserAuthority& 管理授权 为每种类型的用户提供两个会话cookie 装饰控制器,根据什么选择

我的情况可能与大多数情况相反,我希望允许多个同时登录,但仅限于不同类型的用户

  • 用户-有自己的区域
  • 管理员-有自己的区域
当管理员也可以是用户(他们有两个帐户,这主要是为了他们可以从用户PoV检查系统如何工作)并希望同时登录这两个帐户时,就会出现问题

对于表单身份验证,这似乎是不可能的。因此,我不得不稍微“破解”一下,担心自己可能忽略了一些东西

计划:

  • 针对每种用户类型的两个操作筛选器:UserAuthority& 管理授权
  • 为每种类型的用户提供两个会话cookie
  • 装饰控制器,根据什么选择正确的操作过滤器 用户可以访问它
代码可能需要一些整理

我还将使cookie名称更加独特

排除视图/路线等内容,因为它们似乎不相关

将密码盐析/散列出样本,并使用测试值进行固定

用户授权:

public class UserAuthorize : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var authCookie = filterContext.RequestContext.HttpContext.Request.Cookies["User"];

        if (authCookie == null || authCookie.Value == "")
        {
            filterContext.HttpContext.Response.Redirect("/login");
            base.OnActionExecuting(filterContext);
            return;
        }

        FormsAuthenticationTicket authTicket;

        try
        {
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        }
        catch
        {
            filterContext.HttpContext.Response.Redirect("/login");
            base.OnActionExecuting(filterContext);
            return;
        }

        if (authTicket.Expired || authTicket.Expiration <= DateTime.Now)
        {
            filterContext.HttpContext.Response.Redirect("/login");
        }

        base.OnActionExecuting(filterContext);
    }
}
public class AdminAuthorise : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var authCookie = filterContext.RequestContext.HttpContext.Request.Cookies["Admin"];

        if (authCookie == null || authCookie.Value == "")
        {
            filterContext.HttpContext.Response.Redirect("/admin/login");
            base.OnActionExecuting(filterContext);
            return;
        }

        FormsAuthenticationTicket authTicket;

        try
        {
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        }
        catch
        {
            filterContext.HttpContext.Response.Redirect("/admin/login");
            base.OnActionExecuting(filterContext);
            return;
        }

        if (authTicket.Expired || authTicket.Expiration <= DateTime.Now)
        {
            filterContext.HttpContext.Response.Redirect("/admin/login");
        }

        base.OnActionExecuting(filterContext);
    }
}
管理员登录控制器操作:

[HttpPost]
public virtual ActionResult Login(FormCollection form)
{
    if (form["username"] == "admin" && form["password"] == "pass")
    {
        var authTicket = new FormsAuthenticationTicket(
                            1,                             // version
                            form["username"],              // user name
                            DateTime.Now,                  // created
                            DateTime.Now.AddMinutes(20),   // expires
                            false,                         // persistent?
                            ""                             // can be used to store roles
                            );

        string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
        var authCookie = new HttpCookie("User", encryptedTicket);
        Response.Cookies.Add(authCookie);

        // Redirect back to the page you were trying to access
        return RedirectToAction(MVC.Home.Index());
    }
    else
    {
        ModelState.AddModelError("", "Bad info mate");
    }

    return View();
}
[HttpPost]
public virtual ActionResult Login(FormCollection form)
{
    if (form["username"] == "admin" && form["password"] == "pass")
    {
        var authTicket = new FormsAuthenticationTicket(
                            1,                             // version
                            form["username"],              // user name
                            DateTime.Now,                  // created
                            DateTime.Now.AddMinutes(20),   // expires
                            false,                         // persistent?
                            ""                             // can be used to store roles
                            );


        string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
        var authCookie = new HttpCookie("Admin", encryptedTicket);
        Response.Cookies.Add(authCookie);

        // Redirect back to the page you were trying to access
        return RedirectToAction(MVC.Admin.Home.Index());
    }
    else
    {
        ModelState.AddModelError("", "Bad info mate");
    }

    return View();
}
这一切似乎都是明智和安全的吗


在FireFox的页面信息窗口中查看cookie,我看到每种用户类型都有自己的cookie,如果不登录,就无法访问用户类型区域。

此场景需要的是
模拟
,基本上你所要做的就是用模拟的用户数据设置一个假身份验证cookie(这样管理员就可以看到客户看到的内容)

您可能还希望跟踪这一点,这样您就可以在管理员的用户界面上放置有关应用程序状态的用户信息,并为其提供一个结束模拟会话的链接(此时您将恢复以前的cookie),而不是让他“登录两次”


,因为它可能包含一些对您有用的信息(有点旧,但总是有效的)。

首先,您可能应该从AuthorizeAttribute而不是ActionFilterAttribute派生。AutorationFilters在ActionFilters之前执行,并允许短路(即,如果授权筛选器失败,操作筛选器将永远不会执行)。此外,ActionFilters链接在一起,可以按任何顺序执行


其次,将管理员用户名和密码硬编码到属性中不是一个好主意。密码应该是单向散列的。

关于您的数据库模型,我会为一个用户分配几个角色(简单用户、管理员、主管等)。这样,您只需使用默认角色(管理员)登录一次即可,并可以选择切换到其他角色(简单用户PoV)和会话上的存储权限。

很有趣,我会注意添加到我的设置中,但与我的实际问题和使用场景无关。用户名/密码哈希/盐析和从数据库中提取已从我的示例中删除,以保留我真正需要查看的内容