我正在用自定义版本替换(HttpContext.Current.User)IPrincipal,以便我可以存储更多信息登录和用户.我在使用FormsAuthtenticationTicket之前已完成此操作,但其他方式基于Memberhipship和SimpleMembership提供程序.
我的问题是,我可以使用FormsAuthenticationTicket存储我的ICustomPrincipal的cookie,它会干扰或破坏OWIN Identity Pipline吗?我觉得我会混合苹果和橘子.
示例保存:
var user = userRepository.Users.Where(u => u.Email == viewmodel.Email).First(); CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel(); serializeModel.UserId = user.Id; serializeModel.FirstName = user.FirstName; serializeModel.LastName = user.LastName; JavaScriptSerializer serializer = new JavaScriptSerializer(); string userData = serializer.Serialize(serializeModel); FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket( 1,viewmodel.Email,DateTime.Now,DateTime.Now.AddMinutes(15),false,userData); string encTicket = FormsAuthentication.Encrypt(authTicket); HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName,encTicket); Response.Cookies.Add(faCookie);
示例检索:
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(); CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData); CustomPrincipal newUser = new CustomPrincipal(authTicket.Name); newUser.UserId = serializeModel.UserId; newUser.FirstName = serializeModel.FirstName; newUser.LastName = serializeModel.LastName; HttpContext.Current.User = newUser; } }
编辑
我有这个用于创建声明
public ClaimsIdentity CreateIdentity( LoginAttempt loginAttempt) { UserProfile userProfile = GetUserProfile(loginAttempt.UserName); var applicationUser = FindById(userProfile.AspNetUserId); ClaimsIdentity identity; try { identity = UserManager.CreateIdentity(applicationUser,DefaultAuthenticationTypes.ApplicationCookie); } catch (Exception ex) { _log.Error(ex.Message,ex); return null; } //UserManager.GetClaims() identity.AddClaim(new Claim("LoginAttemptId",loginAttempt.LoginAttemptId.ToString(),ClaimValueTypes.String)); identity.AddClaim(new Claim("UserProfileId",loginAttempt.UserProfileId.ToString(),ClaimValueTypes.String)); identity.AddClaim(new Claim("SubscriptionType",userProfile.SubscriptionType,ClaimValueTypes.String)); IList<string> roles= UserManager.GetRoles(applicationUser.Id); identity.AddClaim(new Claim(ClaimTypes.Role,roles.First())); return identity; }
这用于提取
public static long GetLoginAttemptId(this IIdentity principal) { var claimsPrincipal = principal as ClaimsIdentity; if (claimsPrincipal == null) { //throw new Exception("User is not logged in!"); return -1; } var nameClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "LoginAttemptId"); if (nameClaim != null) { return Convert.ToInt64( nameClaim.Value);// as long; } return -1; }
编辑
这些是我得到的主张.我已经注销并重新登录.
解决方法
声称具有完全相同的目的.实际上只有新的API才是这样的.
声明基本上是一个字典< String,String>它存储在auth-cookie中,可通过IPrincipal获得.但是你不需要做ICustomPrincipal,因为你在IPrincipal背后的实际对象是ClaimsPrincipal并且有一个声明列表.
public async override Task CreateIdentityAsync(ApplicationUser applicationUser) { var identity = await base.CreateIdentityAsync(applicationUser,DefaultAuthenticationTypes.ApplicationCookie); identity.AddClaim(new Claim("MyApp:FullName",applicationUser.FullName)); return identity; }
然后你就可以通过扩展从IPrincipal获取这些数据了:
public static String GetFullName(this IPrincipal principal) { var claimsPrincipal = principal as ClaimsPrincipal; if (claimsPrincipal == null) { throw new Exception("User is not logged in!"); } var nameClaim = principal.Claims.FirstOrDefault(c => c.Type == "MyApp:FullName"); if (nameClaim != null) { return nameClaim.Value; } return String.Empty; }
我已经在一些项目中成功使用了这种方法.有关更多代码示例,请参见other similar answers.
这是another article,虽然我不鼓励在MVC应用程序中使用Thread.CurrentPrincipal或ClaimsPrincipal.Current – 你并不总是得到你所期望的,特别是当用户没有登录或在AppPool启动的早期阶段.