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.

Другие вопросы по тегам