2013-11-14 3 views
91

위조 방지 토큰에 문제가 있습니다. ( 괜찮 았던 자체 사용자 클래스를 만들었지 만 지금은 /. 계정/ 페이지를 등록 오류 : 위조 방지 토큰 문제 (MVC 5)

A claim of type ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ' or ' http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider ' was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.

내가이 글을 발견 :

http://stack247.wordpress.com/2013/02/22/antiforgerytoken-a-claim-of-type-nameidentifier-or-identityprovider-was-not-present-on-provided-claimsidentity/

그래서 난 변화를 내 위해 Application_Start 나 여기에 THOD :

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email; 
} 

하지만 난 그렇게 할 때이 오류가 얻을 :

A claim of type ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress ' was not present on the provided ClaimsIdentity.

사람이 전에 건너했습니다? 그렇다면 그것을 해결하는 방법을 알고 있습니까? 사전에

건배,
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> 
{ 
} 

I 프로파일, 내 저장소 단지 간단는 다음과 같습니다 :

public interface IProfile 
{ 
    string Id { get; set; } 
    string CompanyId { get; set; } 

    string UserName { get; set; } 
    string Email { get; set; } 

    string CredentialId { get; set; } 
} 

사용자 클래스는 Microsoft.AspNet.Identity.EntityFramework.User 클래스입니다.

[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] 속성을 장식하는 데 사용하지만, 작동을 중지했던 곳입니다 내 AccountController은 다음과 같습니다.

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 
+0

당신이 우리에게 사용자 정의 사용자 클래스를 보여줄 수 global.asax.cs에 넣고 어떻게 당신이 그것을 사용? – LostInComputer

+0

사용자 정의 사용자 클래스를 추가하고 사용 방법을 추가했습니다. – r3plica

+0

베타 버전을 사용 중입니다. 릴리스 버전으로 업그레이드 한 다음 문제가 계속 발생하는지 확인하는 것이 좋습니다. – LostInComputer

답변

163

시도 설정입니다 희망? 그렇지 않은 경우 :

  1. 이 컨트롤러 어딘가에 중단 점을 넣어 [ValidateAntiForgeryToken] 속성
  2. 를 제거하고
  3. 그런 다음 현재 ClaimsIdentity보고에서 휴식과 주장을 검토
  4. 당신 것 고유하게 생각 하나 찾기 그 주장의 유형에
  5. 설정 사용자 AntiForgeryConfig.UniqueClaimTypeIdentifier을 식별
+24

필자는 이것이 왜 작동하는지주의하는 것이 중요하다고 생각합니다 : 이것은'AntiForgery' 클래스에게'NameIdentifier' ('GetUserId'에 의해 발견 된 사용자 아이디 문자열입니다)를 사용하도록 알려줍니다. 마이크 굿윈 (Mike Goodwin)의 답변 덕분에이 사실을 알게되었습니다. –

+0

"AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;"시도했습니다. 이 오류는 "시퀀스에 하나 이상의 일치하는 요소가 포함되어 있습니다.", 내 경우에는 여러 클레임 (이름, 역할 및 전자 메일 주소)이 있습니다. 이것을 어떻게 분류 할 수 있습니까? – Dhanuka777

+0

@ Dhanuka777, @stackoverflow.com/a/20886332/674700 –

43

은 당신이 당신의 ClaimsIdentity 무엇을 얻을 수 있습니까 클레임 알아 :

은 그만큼 코드 : (global.cs에서)

+3

+1 - 적절한 클레임 유형 식별자를 찾는 방법을 설명해 주셔서 감사합니다. 매우 도움이되었습니다. –

11

TR 시크릿 창에서 링크를 열거 나 해당 도메인의 쿠키를 삭제하십시오 (예 : localhost).

+0

이 작업은 왜 작동하며 문제의 원인은 무엇입니까? – mok

+0

고마워요. –

+0

잘못된 nameidentifier를 가진 세션 쿠키가있을 때 서버가 사용자를 로그인 페이지로 리디렉션하지 않고 잘못된 식별자를 사용하려고 시도하고 적절한 nameidentifier를 가져 오기 때문에 작동합니다. – rawel

1

편집 : 현재이 문제를 더 잘 이해하면 아래 내 대답을 무시해도됩니다.

Global.asax.cs의 Application_Start()에 AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;을 설정하면 문제가 해결되었습니다. http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier이라는 주장이 있지만 원래 질문과 같은 오류가 발생합니다. 그러나 위와 같이 지적하면 어떻게 든 작동합니다. MVC4으로 고유 식별자로 User.Identity.Name를 사용하지 않는 안티 위조 토큰을 시작



. 대신 오류 메시지에서 제공된 두 가지 클레임을 찾습니다.

업데이트 참고가이 사용자가 로그인과 같이 될 때 당신은 당신의 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)); 

하는 것으로 주장 중 하나는 이미 수도 이전부터 거기에 있으니 두 가지를 모두 추가하면 중복 소유권 주장에 오류가 발생합니다. 그렇다면 누락 된 부분을 추가하십시오.

+1

"/ nameidentifier"로 userId를 사용하는 이유를 이해하지만 "/ identityprovider"로 userId를 넣는 이유는 무엇입니까? – AaronLS

14

그냥

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType; 
+0

이것은 매우 간단합니다. 고맙습니다. –

관련 문제