Ajax 设置HttpContext.Current.User

Ajax 设置HttpContext.Current.User,ajax,asp.net-mvc-3,authentication,Ajax,Asp.net Mvc 3,Authentication,我正在开发一个asp.net mvc 3.0应用程序,它有一个简单的身份验证过程。用户填写通过ajax调用发送到服务器的表单并获得响应,但这里的问题是使用以下方法: FormsAuthentication.SetAuthCookie(person.LoginName,false); 不足以填充“HttpContext.Current.User”,需要运行以下方法: FormsAuthentication.RedirectFromLoginPage("..."); 这里的问题是,正如我所提到的

我正在开发一个asp.net mvc 3.0应用程序,它有一个简单的身份验证过程。用户填写通过ajax调用发送到服务器的表单并获得响应,但这里的问题是使用以下方法:

FormsAuthentication.SetAuthCookie(person.LoginName,false);
不足以填充“HttpContext.Current.User”,需要运行以下方法:

FormsAuthentication.RedirectFromLoginPage("...");
这里的问题是,正如我所提到的,loggin表单使用ajax表单,并使用json获取响应,所以重定向是不可能的

如何填写“HttpContext.Current.User”

谢谢

更新:

以下是注册方法:

 [HttpPost]
        public ActionResult Register(Person person)
        {
            var q = da.Persons.Where(x => x.LoginName == person.LoginName.ToLower()).FirstOrDefault();

            if (q != null)
            {
                ModelState.AddModelError("", "Username is repettive, try other one");

                return Json(new object[] { false, this.RenderPartialViewToString("RegisterControl", person) });
            }
            else
            {
                if (person.LoginName.ToLower() == "admin")
                {
                    person.IsAdmin = true;
                    person.IsActive = true;
                }

                da.Persons.Add(person);

                da.SaveChanges();

                FormsAuthentication.SetAuthCookie(person.LoginName,false);
return Json(new object[] { true, "You have registered successfully!" });

}

}

您需要手动设置它。注意这里关于更新请求的当前主体的部分,而不是重新发明轮子——这是您在这里的选择


} FormsAuthentication不支持立即设置用户身份,但您应该能够通过以下方式进行伪装:

HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
            new System.Security.Principal.GenericIdentity(person.LoginName), 
            new string[] { /* fill roles if any */ } );

这是我最终使用的版本,它基于@AdamTuliper MSFT的答案。它只能在登录后立即使用,但在重定向之前,允许其他代码访问
HttpContext.User

  • 如果已经通过身份验证,则不要执行任何操作
  • 不修改cookie,因为这只应用于此请求的生存期
  • 缩短一些内容,并使用userdata更安全一些(不应为null,但…)
在调用SetAuthCookie()后调用此函数,如下所示:

// in login function
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
AuthenticateThisRequest();

private void AuthenticateThisRequest()
{
    //NOTE:  if the user is already logged in (e.g. under a different user account)
    //       then this will NOT reset the identity information.  Be aware of this if
    //       you allow already-logged in users to "re-login" as different accounts 
    //       without first logging out.
    if (HttpContext.User.Identity.IsAuthenticated) return;

    var name = FormsAuthentication.FormsCookieName;
    var cookie = Response.Cookies[name]; 
    if (cookie != null)
    {   
        var ticket = FormsAuthentication.Decrypt(cookie.Value);
        if (ticket != null && !ticket.Expired)
        {
            string[] roles = (ticket.UserData as string ?? "").Split(',');
            HttpContext.User = new GenericPrincipal(new FormsIdentity(ticket), roles);
        }
    }
}

编辑:删除对Request.Cookies的调用,如@AdamTuplier MSFT所述

另外请注意,MVC4模板进行ajax登录(至少是一个ajax对话框)。我不记得之后是否有重定向。尽管(可能有)@EmmanuelN,我更新了问题,添加了一些代码。谢谢。您的解决方案更加复杂,对此我非常感激,但为了简单起见,我选择了卢卡斯·诺沃特尼(LukášNovotný)的答案。Regard此解决方案具有您所需的精确线条。我只是提供了代码作为对另一篇文章的参考。它只是:System.Web.HttpContext.Current.User=newsystem.Security.Principal.GenericPrincipal(newformsidentity(newAuthTicket),roles);其中很多可以简化/删除。另外,如果需要,记得将
请求
更改为
响应
。@AndrewBacker,很有可能-它可能会在新的身份系统中发生变化,但是如果你有更好的方法,请发布它,以便其他人可以使用。诀窍是设置HttpContext.Current.User,它的内容就是您想要设置它的内容。下面的代码还用于续订过期(但有效)令牌。在本例中,重要的代码只是将HttpContext.Current.User(或HttpContext.User)设置为通用主体。因为这只用于身份验证而不用于续订,所以您可以完全忽略请求,因为您永远不会检查它。登录时,它将为空(或过期),因此您并不真正关心。这实际上可以被进一步简化,因为这与“续约”代码重叠,我将在下面更新我的帖子。同意。。我有一个奇怪的案例,它似乎忽略了请求,但这可能是另一个错误。在我的实际代码中,我只是检查响应。。。具有讽刺意味的是,我最终删除了它,并将代码移动到“first request”类型的操作筛选器中,因为登录过程已更改。如果用户经过身份验证并向其他用户注册/登录,则即使为新用户生成了cookie,也会返回旧用户。应该删除第一行或进行一些检查。您是正确的。我将更新代码以显示这一点。函数中的第一行是一个guard子句,如果用户已经通过身份验证,则不执行该操作。这意味着不能在紧急情况下使用,在紧急情况下,您知道用户没有经过身份验证,但您需要设置该信息,以便API调用或其他事情能够正常工作。
// in login function
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
AuthenticateThisRequest();

private void AuthenticateThisRequest()
{
    //NOTE:  if the user is already logged in (e.g. under a different user account)
    //       then this will NOT reset the identity information.  Be aware of this if
    //       you allow already-logged in users to "re-login" as different accounts 
    //       without first logging out.
    if (HttpContext.User.Identity.IsAuthenticated) return;

    var name = FormsAuthentication.FormsCookieName;
    var cookie = Response.Cookies[name]; 
    if (cookie != null)
    {   
        var ticket = FormsAuthentication.Decrypt(cookie.Value);
        if (ticket != null && !ticket.Expired)
        {
            string[] roles = (ticket.UserData as string ?? "").Split(',');
            HttpContext.User = new GenericPrincipal(new FormsIdentity(ticket), roles);
        }
    }
}