Защита от подделки ASP.NET MVC 3 для многопортального приложения, размещенного на одном локальном сервере

У меня 2 сайта, на самом деле они одинаковые. Цель в том, что один из них предназначен для пользователей Интернета, а второй — для локального использования. Теперь они размещены на том же сервере IIS на моей локальной машине. Когда я открываю эти два веб-сайта и пытаюсь получить результат действия, отмеченный [ValidateAntiForgeryToken], у меня возникает проблема, связанная с тем, что в моих файлах cookie есть файлы cookie для моего локального сайта, и есть файл cookie с именем «RequestVerificationToken_Lw». ", который является ключом защиты от подделки. И проблема в том, что оба сайта используют один и тот же файл cookie для хранения этого ключа. И поэтому, если я сделал что-то на одном веб-сайте, я получаю сообщение об ошибке защиты от подделки, когда пытаюсь сделать что-то на другом.

Как я могу изменить домен cookie или любые другие решения для разделения файлов cookie?

Спасибо!


person drunkcamel    schedule 26.07.2011    source источник
comment
Если один сайт предназначен для пользователей интрасети, а другой — для Интернета, не планируете ли вы использовать разные домены? Например, intra.foo.com и extra.foo.com, которые решат ваши проблемы с файлами cookie?   -  person Darin Dimitrov    schedule 27.07.2011
comment
да, это если конечно правильный путь и самое очевидное решение но я думаю бывают такие ситуации когда несколько сайтов размещены на одном сервере и имеют разные порты для доступа к ним и значит невозможно использовать mvc anti- Защита от подделки в этом случае.   -  person drunkcamel    schedule 27.07.2011
comment
конечно, за исключением того, что разные порты означают разные домены => никаких проблем с файлами cookie.   -  person Darin Dimitrov    schedule 27.07.2011
comment
извините, пожалуйста, но на данный момент у меня есть 2 порта для моих 2 веб-сайтов на моем локальном сервере IIS. а мой браузер считает, что это один и тот же хост, просто локальный и не важно на какой порт я подключаюсь. Это проблема. Может быть, мне следует правильно настроить IIS, чтобы каким-то образом разделить эти порты на разные домены или что?   -  person drunkcamel    schedule 27.07.2011
comment
Ты прав. Файлы cookie привязаны к данному домену, а не к домену + порту. Итак, я думаю, вы могли бы объявить в файле hosts две разные записи, соответствующие localhost:123 и localhost:456, а затем запросить свои сайты с соответствующими доменными именами.   -  person Darin Dimitrov    schedule 27.07.2011


Ответы (1)


Итак, давайте посмотрим, что делает ValidateAntiforgeryTokenAttribute (Reflector/ILSpy — ваш друг):

public void OnAuthorization(AuthorizationContext filterContext)
{
    if (filterContext == null)
    {
        throw new ArgumentNullException("filterContext");
    }
    string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null);
    string antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];
    if (httpCookie == null || string.IsNullOrEmpty(httpCookie.Value))
    {
        throw ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    AntiForgeryData antiForgeryData = this.Serializer.Deserialize(httpCookie.Value);
    string text = filterContext.HttpContext.Request.Form[antiForgeryTokenName];
    if (string.IsNullOrEmpty(text))
    {
        throw ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    AntiForgeryData antiForgeryData2 = this.Serializer.Deserialize(text);
    if (!string.Equals(antiForgeryData.Value, antiForgeryData2.Value, StringComparison.Ordinal))
    {
        throw ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    string username = AntiForgeryData.GetUsername(filterContext.HttpContext.User);
    if (!string.Equals(antiForgeryData2.Username, username, StringComparison.OrdinalIgnoreCase))
    {
        throw ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    if (!this.ValidateFormToken(antiForgeryData2))
    {
        throw ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
}

Хорошо, очевидно, что имя файла cookie для токена создается из пути приложения:

    string antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];

Итак, вы создаете свой собственный фильтр, просто копируете и вставляете этот код и меняете его так, чтобы он также учитывал порт (или что-то еще, по чему вы отличаете свои приложения):

    string antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath  + filterContext.HttpContext.Request.Url.Port);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];

Таким образом, имя файла cookie («RequestVerificationToken_Lw») также будет зависеть от порта.

И, конечно же, мы не можем забыть изменить имя этого файла cookie при создании токена. К сожалению, вам нужно будет скопировать и вставить «повторно реализовать» здесь 2 вещи — сначала метод расширения AntiForgeryToken для вызова вашего собственного AntiForgeryWorker, а затем сам AntiForgeryWorker — просто переопределите метод GetAntiForgeryTokenAndSetCookie, это то же самое, что и раньше:

string antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(httpContext.Request.ApplicationPath);

Ну, это кажется беспорядком, и это определенно не СУХОЕ решение, но если вы действительно этого хотите, вы можете сделать это за несколько минут. Просто используйте отражатель и скопируйте-вставьте :)

person rouen    schedule 25.10.2011