web-dev-qa-db-fra.com

Problème de jeton anti-falsification (MVC 5)

J'ai un problème avec le jeton anti-contrefaçon :( J'ai créé ma propre classe d'utilisateurs qui a bien fonctionné, mais je reçois maintenant une erreur chaque fois que je me connecte à /Account/Register L'erreur est la suivante:

Une revendication de type ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ' ou ' http: //schemas.Microsoft.com/accesscontrolservice/2010/07/claims/identityprovider 'n'était pas présent sur ClaimsIdentity fournie. Pour activer la prise en charge des jetons anti-falsification avec une authentification basée sur les revendications, vérifiez que le fournisseur de revendications configuré fournit ces deux revendications sur les instances ClaimsIdentity qu'il génère. Si le fournisseur de revendications configuré utilise à la place un type de revendication différent comme identifiant unique, vous pouvez le configurer en définissant la propriété statique AntiForgeryConfig.UniqueClaimTypeIdentifier.

J'ai trouvé cet article:

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

donc j'ai changé ma méthode Application_Start en ceci:

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

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

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
}

mais quand je fais ça, j'obtiens cette erreur:

Une revendication de type ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress ' n'était pas présente sur ClaimsIdentity fournie.

Est-ce que quelqu'un à déjà rencontré cela avant? Si oui, savez-vous comment le résoudre?

Salut d'avance,
r3plica

Mise à jour 1

Voici ma classe d'utilisateurs personnalisée:

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

Mon profil est simple pour mes dépôts, ressemble à ceci:

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

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

    string CredentialId { get; set; }
}

et la classe User est la classe Microsoft.AspNet.Identity.EntityFramework.User classe. Mon AccountController ressemble à ceci:

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

Auparavant, il était décoré avec l'attribut [ValidateAntiForgeryToken] , mais c'est là qu'il a cessé de fonctionner.

J'espère que c'est assez de code :)

108
r3plica

Essayez de définir (dans global.cs):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
209
Alex Filipovici

Savez-vous quelles revendications vous obtenez dans votre ClaimsIdentity? Si non:

  1. Retirer le [ValidateAntiForgeryToken] attribut
  2. Placez un point d'arrêt quelque part dans votre contrôleur et arrêtez-vous dessus
  3. Ensuite, regardez le ClaimsIdentity actuel et examinez les revendications
  4. Trouvez celui qui identifiera votre utilisateur de manière unique
  5. Met le AntiForgeryConfig.UniqueClaimTypeIdentifier à ce type de revendication
  6. Remettre l'attribut [ValidateAntiForgeryToken]
56
Mike Goodwin

Il suffit de mettre ceci dans global.asax.cs

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
23
mzk

Essayez d'ouvrir le lien dans la fenêtre de navigation privée ou d'effacer le cookie de ce domaine (c'est-à-dire localhost).

12
Gurgen Sargsyan

Edit: Ayant une meilleure compréhension de ce problème en ce moment, vous pouvez ignorer ma réponse ci-dessous.

Réglage AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; dans Application_Start () de Global.asax.cs l'a corrigé pour moi. Même si j'ai la demande http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier _ set, je reçois la même erreur que dans la question initiale. Mais le signaler comme ci-dessus fonctionne en quelque sorte.



À partir de MVC4, le jeton anti-falsification n'utilise pas User.Identity.Name comme identifiant unique. Au lieu de cela, il recherche les deux revendications données dans le message d'erreur.

Mise à jour REMARQUE: cela ne devrait pas être nécessaire Vous pouvez ajouter les revendications manquantes à votre ClaimsIdentity lorsque l'utilisateur est connecté, comme suit:

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

Notez qu’une des revendications peut déjà être présente auparavant, et vous obtiendrez une erreur avec les revendications en double si vous ajoutez les deux. Si oui, ajoutez simplement celui qui manque.

3
cederlof

Dans Global.asax.cs,

1.Ajouter ces espaces de noms

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

2.Ajouter cette ligne dans la méthode Application_Start:

 protected void Application_Start()
 {
       .......
       AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
 } 
1
Kiran Chaudhari
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;

fonctionne pour mon cas, j'utilise l'authentification ADFS.

0
Ashu