У меня есть форма, которую пользователь может опубликовать без входа в систему. Если, однако, его адрес распознается, пароль требуется. Форма пароля проверяется над Ajax и, если успешно, отправляется основная форма. Обе формы требуют действительного AntiForgeryToken.
Уловка, проверка пароля как бипродукт также подписывает пользователя (требование от клиента). Это делает недействительным токен, и основная форма не может быть отправлена.
Я попытался программно генерировать новый токен, но я не могу заставить его работать.
Любые идеи о том, как разрешить это?
Окончательное решение
Я нашел этот вопрос, который будет полезен для типа отражения. Тем не менее, и это является основной причиной того, что при нормальных обстоятельствах вы избегаете взлома внутренних типов, заключается в том, что типы жонглируются между сборками между релизами. Как предлагает Бетти, используйте ILSpy для поиска вещей.
Это окончательный код.
if (signIn)
FormsAuth.SignIn(user.Email, false);
var mvcAssembly = typeof(AntiForgery).Assembly;
var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryData");
string fieldName = Convert.ToString(afdType.InvokeMember(
"GetAntiForgeryTokenName",
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
null,
null,
new object[] { null }));
var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiForgeryDataSerializer");
var serializerCtor = serializerType.GetConstructor(new Type[0]);
object serializer = serializerCtor.Invoke(new object[0]);
string text = HttpContext.Request.Form[fieldName];
object antiForgeryData = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null, serializer, new object[] { text });
afdType.GetProperty("Username").SetValue(antiForgeryData,
signIn ? user.Email : string.Empty,
null);
string newToken = Convert.ToString(serializerType.InvokeMember(
"Serialize",
BindingFlags.InvokeMethod,
null,
serializer,
new object[] { antiForgeryData }));
return Content(JsonConvert.SerializeObject(new
{
success = true,
newAntiForgeryToken = newToken
}), Constant.JsonContentType);
Обновление для веб-страниц 2.0
var mvcAssembly = typeof(AntiForgery).Assembly;
var afdType = mvcAssembly.GetType("System.Web.Helpers.AntiXsrf.AntiForgeryToken");
//string fieldName = Convert.ToString(afdType.InvokeMember(
// "GetAntiForgeryTokenName",
// BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
// null,
// null,
// new object[] { null }));
string fieldName = "__RequestVerificationToken";
var serializerType = mvcAssembly.GetType("System.Web.Helpers.AntiXsrf.AntiForgeryTokenSerializer");
var serializerCtor = serializerType.GetConstructor(new Type[0]);
object serializer = serializerCtor.Invoke(new object[0]);
string text = HttpContext.Request.Form[fieldName];
string newToken = String.Empty;
if (!String.IsNullOrEmpty(text))
{
object antiForgeryToken = serializerType.InvokeMember("Deserialize", BindingFlags.InvokeMethod, null,
serializer, new object[] { text });
afdType.GetProperty("Username").SetValue(antiForgeryToken,
signIn ? user.Email : string.Empty,
null);
newToken = Convert.ToString(serializerType.InvokeMember(
"Serialize",
BindingFlags.InvokeMethod,
null,
serializer,
new[] { antiForgeryToken }));
}