ASP.NET MVC5 OWIN отклоняет длинные URL
Я создаю метод действия ASP.NET MVC5, который реализует конечную точку сброса пароля и принимает переход по электронной почте с сообщением, содержащим токен. Моя реализация использует промежуточное ПО OWIN и очень напоминает примеры приложений ASP.NET Identity 2.1.
В соответствии с примером приложения токен генерируется UserManager
и встраивается в URL, который отправляется пользователю по электронной почте:
var token = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var encoded = HttpServerUtility.UrlTokenEncode(Encoding.UTF8.GetBytes(token));
var uri = new Uri(Url.Link("ResetPasswordRoute", new { id = user.Id, token = encoded }));
Ссылка в сообщении электронной почты предназначена для конечной точки MVC, которая принимает параметр токена в качестве одного из своих сегментов маршрута:
[Route("reset-password/{id}/{token}"]
public async Task<ActionResult> PasswordResetAsync(int id, string token)
{
token = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(token));
// Implementation here
}
Однако запросы к этой конечной точке (с использованием URL-адреса, сгенерированного описанным выше способом) не выполняются с Bad Request - Invalid URL
,
Похоже, этот сбой происходит из-за слишком длинного URL. В частности, если я усекаю сегмент токена, он правильно подключается к конечной точке MVC (хотя, разумеется, параметр токена больше недействителен). В частности, работает следующий усеченный URL-адрес...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFE
... но не получится, если будет добавлен еще один символ...
http://localhost:53717/account/reset-password/5/QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
Я считаю, что настройки конфигурации IIS по умолчанию для maxUrlLength
должно быть совместимо с тем, что я пытаюсь сделать, но я также попытался явно установить его на большее значение, что не решило проблему.
Однако, используя Fiddler для проверки ответа сервера, я вижу, что рабочий URL генерирует ответ сервера со следующим заголовком...
Server: Microsoft-IIS/8.0
... тогда как более длинный URL отклоняется с ответом, содержащим следующий заголовок...
Server: Microsoft-HTTPAPI/2.0
Кажется, это подразумевает, что URL отклоняется не IIS, а компонентом промежуточного программного обеспечения.
Итак, мне интересно, что это за компонент и как я могу обойти его эффект.
Любые предложения, пожалуйста?
Большое спасибо, Тим
Примечание. Хотя моя реализация выше Base64 кодирует токен перед использованием его в URL, я также экспериментировал с более простым подходом, использованным в примере кода, который основан на кодировке URL, предоставленной UrlHelper.RouteUrl
, Оба метода страдают от одной и той же проблемы.
1 ответ
Вы не должны передавать такие длинные значения в пути приложения URL-адреса, поскольку их длина ограничена чем-то вроде 255 символов.
Несколько лучшая альтернатива - использовать параметр строки запроса:
http://localhost:53717/account/reset-password/5?token=QVFBQUFOQ01uZDhCRmRFUmpIb0F3RS9DbCtzQkFBQUFzcko5MEJnYWlrR1RydnVoY2ZwNEpnQUFBQUFDQUFBQUFBQVFaZ0FBQUFFQUFDQUFBQUNVeGZZMzd4OTQ3cE03WWxCakIwRTl4NkVSem1Za2ZUc1JxR2pwYnJSbmJ3QUFBQUFPZ0FBQUFBSUFBQ0FBQUFEcEpnVXFXS0dyM2ZPL2dQcWR1K2x6SkgxN25UVjdMYlE2UCtVRG4rcXBjU0FBQUFEf
Это должно быть безопасно как минимум для 2000 символов (полный URL) в зависимости от настроек браузера и IIS.
Более безопасный и масштабируемый подход заключается в передаче токена внутри заголовка HTTP.