MVC Identity 2 使用 FormsAuthenticationTicket [英] MVC Identity 2 using FormsAuthenticationTicket
问题描述
我正在用自定义版本替换 (HttpContext.Current.User) IPrincipal 以便我可以存储更多信息登录和用户.我在使用 FormsAuthtenticationTicket 之前已经这样做了,但其他方式是基于 Membershipship 和 SimpleMembership 提供者.
我的问题是,我可以使用 FormsAuthenticationTicket 来存储我的 ICustomPrincipal 的 cookie,它会干扰或破坏 OWIN 身份管道吗?我觉得我会混合苹果和橙子.
示例保存:
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 序列化器 = new JavaScriptSerializer();string userData = serializer.Serialize(serializeModel);FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1、viewModel.Email,日期时间.现在,DateTime.Now.AddMinutes(15),错误的,用户数据);字符串 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];如果(authCookie != null){FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);JavaScriptSerializer 序列化器 = new JavaScriptSerializer();CustomPrincipalSerializeModel serializeModel = serializer.Deserialize(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(登录尝试登录尝试){UserProfile userProfile = GetUserProfile(loginAttempt.UserName);var applicationUser = FindById(userProfile.AspNetUserId);ClaimsIdentity 身份;尝试{身份 = UserManager.CreateIdentity(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);}捕获(异常前){_log.Error(ex.Message, ex);返回空;}//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<字符串>角色 = UserManager.GetRoles(applicationUser.Id);identity.AddClaim(new Claim(ClaimTypes.Role, roles.First()));返回身份;}
这是为了提取
public static long GetLoginAttemptId(this IIdentity principal){var claimPrincipal = 作为 ClaimsIdentity 的主体;if (claimsPrincipal == null){//throw new Exception(用户未登录!");返回-1;}var nameClaim = claimPrincipal.Claims.FirstOrDefault(c => c.Type == "LoginAttemptId");if (nameClaim != null){return Convert.ToInt64(nameClaim.Value);//只要;}返回-1;}
编辑这些是我得到的索赔.我已经注销并重新登录.
有些声明的目的完全相同.只有新的 API 才是真正以这种方式使用的.
Claims 基本上是一个 Dictionary
,它存储在 auth-cookie 中并可通过 IPrincipal
获得.但是您不需要执行 ICustomPrincipal
,因为您在 IPrincipal
后面获得的实际对象是 ClaimsPrincipal
并且具有声明列表.>
您需要在登录前向 Identity 对象添加额外信息:
public async override Task CreateIdentityAsync(ApplicationUser applicationUser){var identity = await base.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);identity.AddClaim(new Claim("MyApp:FullName", applicationUser.FullName));返回身份;}
然后您就可以通过扩展从 IPrincipal 中获取这些数据:
public static String GetFullName(这个IPrincipal主体){var claimPrincipal = 作为 ClaimsPrincipal 的主体;if (claimsPrincipal == null){throw new Exception("用户未登录!");}var nameClaim = principal.Claims.FirstOrDefault(c => c.Type == "MyApp:FullName");if (nameClaim != null){返回 nameClaim.Value;}返回 String.Empty;}
我已经在一些项目中成功地使用了这种方法.参见其他类似 更多代码示例的答案.
这是另一篇文章,虽然我不鼓励在 MVC 应用程序中使用 Thread.CurrentPrincipal
或 ClaimsPrincipal.Current
- 你并不总能得到你所期望的,特别是当用户没有登录或未登录时AppPool 启动的早期阶段.
I am replacing the (HttpContext.Current.User) IPrincipal with a custom version so I can store more information login and the user. I have done this before using the FormsAuthtenticationTicket, but those other ways were based on the Memberhipship and SimpleMembership providers.
My question is, can i use the FormsAuthenticationTicket to store the cookie of my ICustomPrincipal with it interfering or breaking in OWIN Identity Pipline? I feel like would i be mixing apples and oranges.
example save:
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);
example retrieve:
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;
}
}
EDIT I have this for the creating the claim
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;
}
and this for extracting
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;
}
EDIT These are the claims I am getting. I have logged off and logged back in.
There are Claims that serve exactly the same purpose. Only new API is actually purposed this way.
Claims are a basically a Dictionary<String, String>
that is stored in auth-cookie and available through IPrincipal
. But you don't need to do ICustomPrincipal
because actual object that you get behind IPrincipal
is ClaimsPrincipal
and that has a list of claims.
You'd add extra information to Idnentity object just before the login:
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;
}
And then you'd be able to get this data out from IPrincipal via extension:
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;
}
I have used this method successfully in a few projects already. See other similar answers for more code samples.
Here is another article, though I discourage from using Thread.CurrentPrincipal
or ClaimsPrincipal.Current
in MVC application - you don't always get what you expect, especially when user is not logged in or on early stages of AppPool start up.
这篇关于MVC Identity 2 使用 FormsAuthenticationTicket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!