ASP.NET MVC - Set custom IIdentity or IPrincipal

后端 未结 9 1393
忘了有多久
忘了有多久 2020-11-21 23:06

I need to do something fairly simple: in my ASP.NET MVC application, I want to set a custom IIdentity / IPrincipal. Whichever is easier / more suitable. I want to extend the

9条回答
  •  梦如初夏
    2020-11-21 23:40

    I tried the solution suggested by LukeP and found that it doesn't support the Authorize attribute. So, I modified it a bit.

    public class UserExBusinessInfo
    {
        public int BusinessID { get; set; }
        public string Name { get; set; }
    }
    
    public class UserExInfo
    {
        public IEnumerable BusinessInfo { get; set; }
        public int? CurrentBusinessID { get; set; }
    }
    
    public class PrincipalEx : ClaimsPrincipal
    {
        private readonly UserExInfo userExInfo;
        public UserExInfo UserExInfo => userExInfo;
    
        public PrincipalEx(IPrincipal baseModel, UserExInfo userExInfo)
            : base(baseModel)
        {
            this.userExInfo = userExInfo;
        }
    }
    
    public class PrincipalExSerializeModel
    {
        public UserExInfo UserExInfo { get; set; }
    }
    
    public static class IPrincipalHelpers
    {
        public static UserExInfo ExInfo(this IPrincipal @this) => (@this as PrincipalEx)?.UserExInfo;
    }
    
    
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task Login(LoginModel details, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                AppUser user = await UserManager.FindAsync(details.Name, details.Password);
    
                if (user == null)
                {
                    ModelState.AddModelError("", "Invalid name or password.");
                }
                else
                {
                    ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                    AuthManager.SignOut();
                    AuthManager.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);
    
                    user.LastLoginDate = DateTime.UtcNow;
                    await UserManager.UpdateAsync(user);
    
                    PrincipalExSerializeModel serializeModel = new PrincipalExSerializeModel();
                    serializeModel.UserExInfo = new UserExInfo()
                    {
                        BusinessInfo = await
                            db.Businesses
                            .Where(b => user.Id.Equals(b.AspNetUserID))
                            .Select(b => new UserExBusinessInfo { BusinessID = b.BusinessID, Name = b.Name })
                            .ToListAsync()
                    };
    
                    JavaScriptSerializer serializer = new JavaScriptSerializer();
    
                    string userData = serializer.Serialize(serializeModel);
    
                    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                             1,
                             details.Name,
                             DateTime.Now,
                             DateTime.Now.AddMinutes(15),
                             false,
                             userData);
    
                    string encTicket = FormsAuthentication.Encrypt(authTicket);
                    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
                    Response.Cookies.Add(faCookie);
    
                    return RedirectToLocal(returnUrl);
                }
            }
            return View(details);
        }
    

    And finally in Global.asax.cs

        protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    
            if (authCookie != null)
            {
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                PrincipalExSerializeModel serializeModel = serializer.Deserialize(authTicket.UserData);
                PrincipalEx newUser = new PrincipalEx(HttpContext.Current.User, serializeModel.UserExInfo);
                HttpContext.Current.User = newUser;
            }
        }
    

    Now I can access the data in views and controllers simply by calling

    User.ExInfo()
    

    To log out I just call

    AuthManager.SignOut();
    

    where AuthManager is

    HttpContext.GetOwinContext().Authentication
    

提交回复
热议问题