Sahte olmayan belirteç sorunu (MVC 5)


122

Sahteciliği önleme belirteciyle ilgili bir sorun yaşıyorum :( İyi çalışan kendi Kullanıcı sınıfımı oluşturdum ancak şimdi / Hesap / Kayıt sayfasına her gittiğimde bir hata alıyorum . Hata:

' Http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ' veya ' http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider ' türünde bir hak talebi sağlanan ClaimsIdentity'de mevcut değil. Talep tabanlı kimlik doğrulamayla sahteciliği önleme belirteci desteğini etkinleştirmek için, lütfen yapılandırılan talep sağlayıcısının ürettiği ClaimsIdentity örneklerinde bu taleplerin her ikisini de sağladığını doğrulayın. Yapılandırılan talep sağlayıcısı bunun yerine benzersiz bir tanımlayıcı olarak farklı bir talep türü kullanıyorsa, AntiForgeryConfig.UniqueClaimTypeIdentifier statik özelliği ayarlanarak yapılandırılabilir.

Bu makaleyi buldum:

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

bu yüzden Application_Start yöntemimi şu şekilde değiştirdim :

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

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

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
}

ama bunu yaptığımda şu hatayı alıyorum:

Sağlanan ClaimsIdentity'de " http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress " türünde bir hak talebi mevcut değildi.

Daha önce hiçkimse bununla karşılaştı mı? Eğer öyleyse, nasıl çözeceğinizi biliyor musunuz?

Şimdiden şerefe,
r3plica

Güncelleme 1

İşte benim özel kullanıcı sınıfım:

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>
{
}

Profilim arşivlerim için basittir, şuna benzer:

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

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

    string CredentialId { get; set; }
}

ve User sınıfı Microsoft.AspNet.Identity.EntityFramework.User sınıfıdır. My AccountController şöyle görünür:

[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);
        }
    }
}

Eskiden [ValidateAntiForgeryToken] özniteliğiyle dekore edilmişti , ancak burada çalışmayı durdurdu.

Umarım bu yeterli koddur :)


Bize özel Kullanıcı sınıfını ve bunu nasıl kullandığınızı gösterebilir misiniz?
LostInComputer

Özel Kullanıcı sınıfını ve onu nasıl kullandığımı ekledim.
r3plica

Beta sürümünü kullanıyorsunuz. Sürüme yükseltmenizi ve ardından sorunun devam edip etmediğini kontrol etmenizi öneririm.
LostInComputer

Yanıtlar:


230

Ayarlamayı deneyin (global.cs içinde):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

33
Bunun neden işe yaradığına dikkat etmenin önemli olduğunu düşünüyorum: Bu, AntiForgerysınıfa NameIdentifier(tarafından bulunan kullanıcı kimliği dizesi olan) kullanmasını söyler GetUserId. Mike Goodwin'in bunu öğrenmeme yardım eden cevabı sayesinde!
Matt DeKrey

"AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;" ve "Sıra birden fazla eşleşen öğe içeriyor" hatasını aldım, benim durumumda birkaç talep var (ad, rol ve e-posta adresi). Bunu nasıl çözebilirim?
Dhanuka777

9
Bunu Global.asax.cs'de belirledim
Mike Taverne

6
Kimlik doğrulamanız olarak OpenId (yani Azure ActiveDirectory) kullanıyorsanız da çözüm budur.
guysherman

6
Tam ad alanları .. ClaimTypes'in nerede tutulduğunu bulmak için biraz araştırma yapmak zorunda kaldım. System.Web.Helpers.AntiForgeryConfig.UniqueClaimTypeIdentifier = System.Security.Claims.ClaimTypes.NameIdentifier;
Mark Rowe

65

ClaimsIdentity'nizde hangi iddiaları aldığınızı biliyor musunuz? Değilse:

  1. [ValidateAntiForgeryToken]Özniteliği kaldırın
  2. Denetleyicinizin herhangi bir yerine bir kesme noktası koyun ve kırın
  3. Ardından akıma bakın ClaimsIdentityve iddiaları inceleyin
  4. Kullanıcınızı benzersiz şekilde tanımlayacağını düşündüğünüz birini bulun
  5. AntiForgeryConfig.UniqueClaimTypeIdentifierBu talep türüne ayarlayın
  6. [ValidateAntiForgeryToken]Özniteliği geri koyun

3
Doğrudan kaşıkla besleme cevabını vermekten daha fazlası, bu arka planı söyler ve kendini keşfetmeyi sağlar. :) Çok teşekkürler
NitinSingh

2
6. [ValidateAntiForgeryToken]Özniteliği geri koyun
Scott Fraley

1
bu bana gerçekten yardımcı oldu. Görünüşe göre benim localhost'umda çalışan başka bir uygulamadan, hiçbir hak talebinin kullanılmadığı uygulamamda bir hak talebinde bulundum (bu yüzden iddialar bana garip geldi). Yani diğer uygulamadan çıkış yaptığımda, iddialar gitti ve hata da öyleydi. Canlı test ortamında bu siteler daha ayrılmıştır. Bu yüzden yukarıda belirtilen çözüme ihtiyacım olduğunu düşünüyorum, ancak yalnızca yerel kalkınma için.
Michel

26

Bunu global.asax.cs dosyasına koyun

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;

Teşekkürler. Anlamadığım şey, bu değişikliği neden yapmak zorunda olduğum, dün gece kodumla yaşadığım birkaç farklı sorunu düzelttim ve her şey yolunda gitti. Hiçbir şeyi değiştirmeden, bunu başka bir makinede test ettim ve hepsi birkaç dakika öncesine kadar çalıştı.
Artorias2718

14

Bağlantıyı gizli pencerede açmayı deneyin veya bu alandaki çerezleri temizleyin (örn. Localhost).


Bu neden işe yarıyor ve sorunun nedeni nedir?
mok

Bu, geçersiz ad tanımlayıcıya sahip bir oturum tanımlama bilgisine sahip olduğunuzda, sunucunun kullanıcıyı oturum açma sayfasına yeniden yönlendirmeden geçersiz tanımlayıcıyı kullanmaya ve uygun ad tanımlayıcıyı almaya çalışmasından dolayı işe yarar.
rawel

3

Düzenleme: Şu anda bu sorunu daha iyi anladıktan sonra, aşağıdaki cevabımı göz ardı edebilirsiniz.

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;Global.asax.cs'nin Application_Start () içindeki ayar benim için düzeltildi. Talep http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifiersetine sahip olsam da , orijinal soruda olduğu gibi aynı hatayı alıyorum. Ama yukarıdaki gibi işaret etmek bir şekilde işe yarıyor.



MVC4 ile başlayarak sahtecilik önleme belirteci User.Identity.Namebenzersiz tanımlayıcı olarak kullanılmaz. Bunun yerine, hata mesajında ​​verilen iki iddiayı arar.

Güncelleme NOT: Bu gerekli olmamalıdır Eksik talepleri ClaimsIdentity kullanıcı oturum açarken aşağıdaki gibi ekleyebilirsiniz:

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));

Hak taleplerinden birinin daha önce mevcut olabileceğini ve ikisini de eklerseniz yinelenen hak talepleriyle ilgili bir hata alacağınızı unutmayın. Eğer öyleyse, eksik olanı ekleyin.


1
"/ Nameidentifier" olarak userId'yi neden kullandığınızı anlıyorum, ancak userId'yi neden "/ identprovider" olarak giriyorsunuz?
AaronLS

2

Global.asax.cs içinde,

1. Bu ad alanlarını ekleyin

using System.Web.Helpers;
using System.Security.Claims;

2. Bu satırı Application_Start yöntemine ekleyin:

 protected void Application_Start()
 {
       .......
       AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
 } 

Yukarıda cevaplananlardan daha fazla değeri nasıl katıyor
NitinSingh

Kullanımları eklediğiniz için teşekkürler. @NitinSingh Bunun daha fazla değer kattığını düşünüyorum çünkü projemdeki üç potansiyel ad alanından hangisini kullanacağımı bilmiyordum.
Keisha W

Yeni bir işlevsellik eklediğinizde, doğru referanslar isteyecektir.
Derlendikten

0
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;

benim durumum için çalışıyor ADFS Kimlik Doğrulaması kullanıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.