ASP.NET MVC 3 Защита от подделки для многопортального приложения, размещенного на одном локальном сервере - PullRequest
4 голосов
/ 26 июля 2011

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

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

Спасибо!

1 Ответ

0 голосов
/ 25 октября 2011

Хорошо, давайте посмотрим, что делает 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, это то же самое, что и раньше:1012 *

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

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

...