위조 방지 토큰 문제 (MVC 5)
위조 방지 토큰에 문제가 있습니다. (잘 작동하는 자체 사용자 클래스를 만들었지 만 / Account / Register 페이지 로 이동할 때마다 오류가 발생합니다. 오류는 다음과 같습니다.
' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier '또는 ' http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider ' 유형의 청구 는 제공된 ClaimsIdentity에 없습니다. 클레임 기반 인증으로 위조 방지 토큰을 지원하려면 구성된 클레임 공급자가 생성 한 ClaimsIdentity 인스턴스에서이 클레임을 모두 제공하는지 확인하십시오. 구성된 클레임 공급자가 대신 다른 클레임 유형을 고유 식별자로 사용하는 경우 정적 속성 AntiForgeryConfig.UniqueClaimTypeIdentifier를 설정하여 구성 할 수 있습니다.
이 기사를 찾았습니다.
그래서 Application_Start 메소드를 다음과 같이 변경 했습니다.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
}
그러나 그렇게하면이 오류가 발생합니다.
' http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress ' 유형의 클레임은 제공된 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>
{
}
내 프로필은 프로필이 간단합니다.
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의 클래스. 내 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] 속성 으로 장식 되었지만 작동이 중지 된 곳입니다.
I hope that is enough code :)
Try setting (in global.cs):
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
Do you know what claims you do get in your ClaimsIdentity? If not:
- Remove the
[ValidateAntiForgeryToken]
attribute - Put a breakpoint somewhere in your controller and break at it
- Then look at the current
ClaimsIdentity
and examine the claims - Find one that you think will uniquely identify your user
- Set the
AntiForgeryConfig.UniqueClaimTypeIdentifier
to that claim type - Put back the
[ValidateAntiForgeryToken]
attribute
Just put this in global.asax.cs
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
Try open link in incognito window or clear cookie from that domain(i.e. localhost).
Edit: Having a greater understanding of this problem at this moment, you can disregard my answer below.
Setting AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
in Application_Start() of Global.asax.cs fixed it for me. Even though I have the claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
set, I get the same error as in the original question. But pointing it out as above somehow works.
Starting with MVC4 the anti-forgery-token doesn't use User.Identity.Name
as the unique identifier. Instead it looks for the two claims given in the error message.
Update NOTE: This should not be needed You can add the missing claims to your ClaimsIdentity when the user is being logged in, like so:
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));
Note that one of the claims might already be there from before, and you will get an error with duplicate claims if you add both. If so, just add the one missing.
In Global.asax.cs,
1.Add these namespaces
using System.Web.Helpers;
using System.Security.Claims;
2.Add this line in method Application_Start:
protected void Application_Start()
{
.......
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimsIdentity.DefaultNameClaimType;
}
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;
works for my case i am using ADFS Authentication.
참고URL : https://stackoverflow.com/questions/19977833/anti-forgery-token-issue-mvc-5
'IT story' 카테고리의 다른 글
DialogFragment에 인수 전달 (0) | 2020.08.04 |
---|---|
내용 편집 가능한 추가 방지 (0) | 2020.08.04 |
버전이없는 버전의 Subversion 자동 제거 (0) | 2020.08.04 |
Java 또는 C #에서 다중 상속이 허용되지 않는 이유는 무엇입니까? (0) | 2020.08.04 |
Ruby 문자열에서“\ n”문자열을 어떻게 제거합니까? (0) | 2020.08.04 |