防伪令牌问题(MVC 5)

我有一个反伪造令牌的问题:(我已经创build了我自己的用户类,工作正常,但现在我得到一个错误,每当我去/帐户/注册页面。错误是:

types为“ http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ”或“ http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider ”的声明是不在提供的ClaimsIdentity上。 要启用基于声明的身份validation的防伪标记支持,请validationconfiguration的声明提供程序是否在其生成的ClaimsIdentity实例上提供了这两个声明。 如果configuration的声明提供程序使用不同的声明types作为唯一标识符,则可以通过设置静态属性AntiForgeryConfig.UniqueClaimTypeIdentifier来configuration它。

我发现这篇文章:

AntiForgeryToken: A Claim of Type NameIdentifier or IdentityProvider Was Not Present on Provided ClaimsIdentity

所以我改变了我的Application_Start方法:

protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email; } 

但是当我这样做,我得到这个错误:

提供的ClaimsIdentity中没有“ http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress ”types的声明。

有没有人遇到过这个? 如果是这样,你知道如何解决它?

提前欢呼,
r3plica

更新1

这是我的自定义用户类:

 public class Profile : User, IProfile { public Profile() : base() { this.LastLoginDate = DateTime.UtcNow; this.DateCreated = DateTime.UtcNow; } public Profile(string userName) : base(userName) { this.CreatedBy = this.Id; this.LastLoginDate = DateTime.UtcNow; this.DateCreated = DateTime.UtcNow; this.IsApproved = true; } [NotMapped] public HttpPostedFileBase File { get; set; } [Required] public string CompanyId { get; set; } [Required] public string CreatedBy { get; set; } public string ModifiedBy { get; set; } public DateTime DateCreated { get; set; } public DateTime? DateModified { get; set; } public DateTime LastLoginDate { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredTitle")] public string Title { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredFirstName")] public string Forename { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredLastName")] public string Surname { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredEmail")] public string Email { get; set; } public string JobTitle { get; set; } public string Telephone { get; set; } public string Mobile { get; set; } public string Photo { get; set; } public string LinkedIn { get; set; } public string Twitter { get; set; } public string Facebook { get; set; } public string Google { get; set; } public string Bio { get; set; } public string CompanyName { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredCredentialId")] public string CredentialId { get; set; } [Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName = "RequiredSecurityCode")] public bool IsLockedOut { get; set; } public bool IsApproved { get; set; } [Display(Name = "Can only edit own assets")] public bool CanEditOwn { get; set; } [Display(Name = "Can edit assets")] public bool CanEdit { get; set; } [Display(Name = "Can download assets")] public bool CanDownload { get; set; } [Display(Name = "Require approval to upload assets")] public bool RequiresApproval { get; set; } [Display(Name = "Can approve assets")] public bool CanApprove { get; set; } [Display(Name = "Can synchronise assets")] public bool CanSync { get; set; } public bool AgreedTerms { get; set; } public bool Deleted { get; set; } } public class ProfileContext : IdentityStoreContext { public ProfileContext(DbContext db) : base(db) { this.Users = new UserStore<Profile>(this.DbContext); } } public class ProfileDbContext : IdentityDbContext<Profile, UserClaim, UserSecret, UserLogin, Role, UserRole> { } 

我的configuration文件只是简单的我的知识库,看起来像这样:

 public interface IProfile { string Id { get; set; } string CompanyId { get; set; } string UserName { get; set; } string Email { get; set; } string CredentialId { get; set; } } 

User类是Microsoft.AspNet.Identity.EntityFramework.User类。 我的AccountController看起来像这样:

 [Authorize] public class AccountController : Controller { public IdentityStoreManager IdentityStore { get; private set; } public IdentityAuthenticationManager AuthenticationManager { get; private set; } public AccountController() { this.IdentityStore = new IdentityStoreManager(new ProfileContext(new ProfileDbContext())); this.AuthenticationManager = new IdentityAuthenticationManager(this.IdentityStore); } // // GET: /Account/Register [AllowAnonymous] public ActionResult Register() { return View(); } // // POST: /Account/Register [HttpPost] [AllowAnonymous] public async Task<ActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { try { // Create a profile, password, and link the local login before signing in the user var companyId = Guid.NewGuid().ToString(); var user = new Profile(model.UserName) { CompanyId = companyId, Title = model.Title, Forename = model.Forename, Surname = model.Surname, Email = model.Email, CompanyName = model.CompanyName, CredentialId = model.CredentialId }; if (await IdentityStore.CreateLocalUser(user, model.Password)) { //Create our company var company = new Skipstone.Web.Models.Company() { Id = companyId, CreatedBy = user.Id, ModifiedBy = user.Id, Name = model.CompanyName }; using (var service = new CompanyService()) { service.Save(company); } await AuthenticationManager.SignIn(HttpContext, user.Id, isPersistent: false); return RedirectToAction("Setup", new { id = companyId }); } else { ModelState.AddModelError("", "Failed to register user name: " + model.UserName); } } catch (IdentityException e) { ModelState.AddModelError("", e.Message); } } // If we got this far, something failed, redisplay form return View(model); } // // POST: /Account/Setup public ActionResult Setup(string id) { var userId = User.Identity.GetUserId(); using (var service = new CompanyService()) { var company = service.Get(id); var profile = new Profile() { Id = userId, CompanyId = id }; service.Setup(profile); return View(company); } } } 

它曾经用[ValidateAntiForgeryToken]属性来装饰,但这是停止工作的地方。

我希望是足够的代码:)

尝试设置(在global.cs中):

 AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 

你知道你的索赔身份是什么吗? 如果不:

  1. 删除[ValidateAntiForgeryToken]属性
  2. 在你的控制器的某个地方放一个断点,并打断它
  3. 然后看看当前的ClaimsIdentity并检查索赔
  4. find一个你认为会唯一标识你的用户
  5. AntiForgeryConfig.UniqueClaimTypeIdentifier设置为该声明types

把这个放在global.asax.cs中

 AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType; 

尝试在隐身窗口中打开链接或清除该域(即本地主机)的cookie。

编辑:在这个时候对这个问题有更深的理解,你可以忽略下面的答案。

设置AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 在Global.asax.cs的Application_Start()中为我解决了这个问题。 即使我有索赔http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier集合,我得到了与原始问题相同的错误。 但是,如上所述,以某种方式工作。



从MVC4开始,防伪标记不使用User.Identity.Name作为唯一标识符。 相反,它会查找错误消息中给出的两个声明。

更新注意:这不应该需要您可以在用户login时将丢失的声明添加到您的ClaimsIdentity中,如下所示:

 string userId = TODO; var identity = System.Web.HttpContext.Current.User.Identity as ClaimsIdentity; identity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", userId)); identity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", userId)); 

请注意,之前的某个声明可能已经存在,如果您同时添加了这两个声明,则会出现重复声明的错误。 如果是这样,只需添加一个缺less的。