У меня есть форма, которую пользователь может публиковать без входа в систему. Если, однако, его электронная почта распознана, требуется пароль.Форма пароля проверяется через 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 }));
}