Tengo un problema con el token anti-falsificación :( He creado mi propia clase de usuario que funcionó bien, pero ahora recibo un error cada vez que voy a la página / Cuenta / Registro . El error es:
Un reclamo del tipo ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ' o ' http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider ' fue no presente en el ClaimsIdentity proporcionado. Para habilitar el soporte de token anti-falsificación con autenticación basada en reclamos, verifique que el proveedor de reclamos configurado proporcione ambos reclamos en las instancias de ClaimsIdentity que genera. Si, en cambio, el proveedor de notificaciones configurado utiliza un tipo de notificación diferente como identificador único, se puede configurar estableciendo la propiedad estática AntiForgeryConfig.UniqueClaimTypeIdentifier.
Encontré este artículo:
así que cambié mi método Application_Start a esto:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
}
pero cuando hago eso, aparece este error:
Un reclamo del tipo ' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress ' no estaba presente en el ClaimsIdentity proporcionado.
¿Alguien se ha encontrado con esto antes? Si es así, ¿sabes cómo solucionarlo?
Saludos de antemano,
r3plica
Actualización 1
Aquí está mi clase de usuario personalizada:
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>
{
}
Mi perfil es simple para mis repositorios, se ve así:
public interface IProfile
{
string Id { get; set; }
string CompanyId { get; set; }
string UserName { get; set; }
string Email { get; set; }
string CredentialId { get; set; }
}
y la clase de usuario es la clase Microsoft.AspNet.Identity.EntityFramework.User . Mi AccountController se ve así:
[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);
}
}
}
Solía estar decorado con el atributo [ValidateAntiForgeryToken] , pero ahí es donde dejó de funcionar.
Espero que sea suficiente código :)
Respuestas:
Intente configurar (en global.cs):
fuente
AntiForgery
clase que useNameIdentifier
(que es la cadena de identificación de usuario encontrada porGetUserId
). ¡Gracias a la respuesta de Mike Goodwin por ayudarme a aprender esto!¿Sabe qué reclamos obtiene en su ClaimsIdentity? Si no:
[ValidateAntiForgeryToken]
atributoClaimsIdentity
y examine las afirmaciones.AntiForgeryConfig.UniqueClaimTypeIdentifier
en ese tipo de reclamo[ValidateAntiForgeryToken]
atributofuente
[ValidateAntiForgeryToken]
atributoSimplemente ponga esto en global.asax.cs
fuente
Intente abrir el enlace en la ventana de incógnito o borrar la cookie de ese dominio (es decir, localhost).
fuente
Editar: Teniendo una mayor comprensión de este problema en este momento, puede ignorar mi respuesta a continuación.
La configuración
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
en Application_Start () de Global.asax.cs lo arregló para mí. Aunque tengo el reclamohttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
establecido, obtengo el mismo error que en la pregunta original. Pero señalarlo como arriba funciona de alguna manera.Comenzando con MVC4, el token anti-falsificación no se usa
User.Identity.Name
como identificador único. En su lugar, busca las dos afirmaciones dadas en el mensaje de error.Actualización NOTA: Esto no debería ser necesario . Puede agregar las reclamaciones que faltan a su ClaimsIdentity cuando el usuario está iniciando sesión, así:
Tenga en cuenta que es posible que una de las reclamaciones ya esté allí desde antes, y obtendrá un error con reclamaciones duplicadas si agrega ambas. Si es así, simplemente agregue el que falta.
fuente
En Global.asax.cs,
1.Añadir estos espacios de nombres
2.Agregue esta línea en el método Application_Start:
fuente
funciona para mi caso estoy usando la autenticación ADFS.
fuente