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