setting HttpContext.Current.User

2019-01-26 09:54发布

问题:

I am developing an asp.net mvc 3.0 application which has a simple authentication process. User fills a form which is sent to server by ajax call and gets response, but the problem here is that using the following method :

FormsAuthentication.SetAuthCookie(person.LoginName,false);

is not enough to fill 'HttpContext.Current.User' and it needs the below method to be run :

FormsAuthentication.RedirectFromLoginPage("...");

Problem here is that as i mentioned, the loggin form uses an ajax form, and get responses with json, so redirecting is not possible.

How could I fill 'HttpContext.Current.User' ?

Thanks.

Update :

Here is register method :

 [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!" });

}

}

回答1:

Here is the version I ended up using, which is based on the answer by @AdamTuliper-MSFT. It is only meant to be used right after logging in, but before redirect, to allow other code to access HttpContext.User.

  • Don't do anything if already authenticated
  • Doesn't modify the cookie, since this should only be used for the lifetime of this request
  • Shorten some things, and a little safer with userdata (should never be null, but...)

Call this after you call SetAuthCookie(), like below:

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

Edit: Remove call to Request.Cookies, as @AdamTuplier-MSFT mentioned.



回答2:

FormsAuthentication doesn't support immediate setting of user's identity, but you should be able to fake it by something like this:

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


回答3:

You need to manually set it. Rather than reinventing the wheel, note the section here on updating the current principal for the request - thats your option here.

How to set Request.IsAuthenticated to true when not using FormsAuthentication.RedirectFromLoginPage?

public void RenewCurrentUser()
{
    System.Web.HttpCookie authCookie =
        System.Web.HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = null;
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);

if (authTicket != null && !authTicket.Expired) { FormsAuthenticationTicket newAuthTicket = authTicket; if (FormsAuthentication.SlidingExpiration) { newAuthTicket = FormsAuthentication.RenewTicketIfOld(authTicket); } string userData = newAuthTicket.UserData; string[] roles = userData.Split(','); System.Web.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(newAuthTicket), roles); } }

}