zmo*_*edi 2 asp.net-mvc login claims asp.net-identity asp.net-identity-2
我正在使用ASP.NET MVC 5和Identity 2与Entity Framework 6的系统.当用户登录时,我向该登录会话添加一些声明.我不想使用索赔表.
对于我的一个主张,我确实喜欢这样:
public class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
//We add the display name so that the _LoginPartial can pick it up;
userIdentity.AddClaim(new Claim("DisplayName", FirstName + " " + LastName));
// Add custom user claims here
return userIdentity;
}
public virtual ICollection<UserInsurance> UserInsurances { get; set; }
public User()
{
UserInsurances = new List<UserInsurance>();
}
}
Run Code Online (Sandbox Code Playgroud)
并且为了获得索赔:
var claimsIdentity = User.Identity as System.Security.Claims.ClaimsIdentity;
var displayNameClaim = claimsIdentity != null
? claimsIdentity.Claims.SingleOrDefault(x => x.Type == "DisplayName")
: null;
var nameToDisplay = displayNameClaim == null ? User.Identity.Name : displayNameClaim.Value;
Run Code Online (Sandbox Code Playgroud)
这很好用.但问题是当我需要一个不在User表中的字段时.实际上,它是用户导航属性(UserInsurances)中的一条记录,我需要一个linq查询来访问它.
var lastUserInsurance = UserInsurances.OrderByDescending(x => x.CompanyInsuranceId).First();
userIdentity.AddClaim(new Claim("CompanyInsuranceId", lastUserInsurance.CompanyInsuranceId.ToString()));
Run Code Online (Sandbox Code Playgroud)
如果我将此代码放在GenerateUserIdentityAsync方法(如"DisplayName")中,则UserInsurances为null.所以我应该将此代码添加到登录操作并在用户成功登录后添加.但我试过了,它不起作用.我不知道为什么,但是当我想要访问该声明时,它就不存在了.
public virtual async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
var user = _user.Include(x => x.UserInsurances).FirstOrDefault(x => x.NationalCode == model.UserName);
var identity = await SignInManager.CreateUserIdentityAsync(user);
var lastUserInsurance = user.UserInsurances.OrderByDescending(x => x.CompanyInsuranceId).FirstOrDefault();
identity.AddClaim(new Claim("CompanyInsuranceId", lastUserInsurance.CompanyInsuranceId.ToString()));
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
return View(model);
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我为什么我无法访问此声明并且它不存在?我不知道如何实现此方案并在我的应用程序的所有部分中访问"CompanyInsuranceId"声明.
您必须在签署用户之前添加您的声明.因此,如果由于任何原因您无法填写您的声明GenerateUserIdentityAsync方法.只需Identity在登录操作方法中生成对象,然后登录即可.考虑这个例子:
public async Task<ActionResult> Login(LoginViewModel model,string returnUrl)
{
var user = UserManager.Find(model.Email, model.Password);
// now you have the user object do what you to gather claims
if(user!=null)
{
var ident = UserManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie);
ident.AddClaims(new[] {
new Claim("MyClaimName","MyClaimValue"),
new Claim("YetAnotherClaim","YetAnotherValue"),
});
AuthenticationManager.SignIn(
new AuthenticationProperties() { IsPersistent = true },
ident);
return RedirectToLocal(returnUrl);
}
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您可以执行任何想要收集声明并填写身份的内容,然后登录用户.
但是如果你想使用SignInManager.PasswordSignInAsync()方法只是简单地覆盖SignInManager.CreateUserIdentityAsync()方法,那么你可以生成所需的声明.例如,如果你需要DbContext为你的喂养要求简单,你可以取注入额外的信息DbContext中SignInManager,并在使用CreateUserIdentityAsync()这样的方法:
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
private readonly ApplicationDbContext _context;
public ApplicationSignInManager(
ApplicationUserManager userManager,
IAuthenticationManager authenticationManager,
ApplicationDbContext context)
: base(userManager, authenticationManager)
{
_context=context;
}
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
var companyInsuranceId=_context.Users
.Where(u=>u.NationalCode == user.UserName)
.Select(u=>u.UserInsurances
.OrderByDescending(x => x.CompanyInsuranceId)
.Select(x=>x.CompanyInsuranceId)
.FirstOrDefault())
.FirstOrDefault();
var ident=user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
ident.AddClaim(new Claim("CompanyInsuranceId",
companyInsuranceId.ToString()));
return ident;
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(
context.GetUserManager<ApplicationUserManager>(),
context.Authentication,
context.Get<ApplicationDbContext>());
}
}
Run Code Online (Sandbox Code Playgroud)
现在只是写作
var result = await SignInManager.PasswordSignInAsync(
model.UserName, model.Password,
model.RememberMe, shouldLockout: false);
Run Code Online (Sandbox Code Playgroud)
您可以签署用户并注入其他声明.
| 归档时间: |
|
| 查看次数: |
1481 次 |
| 最近记录: |