Подтвердить что ты не робот

Как получить значение AntiForgeryToken без скрытого ввода

@Html.AntiForgeryToken() отображает скрытый ввод

<input name="__RequestVerificationToken" type="hidden" value="GuiNIwhIJZjINHhuS_8FenaFDXIiaE" />

Как я могу получить только токен? Без уродливого кода:

public static IHtmlString AntiForgeryTokenValue(this HtmlHelper htmlHelper) {
        var field = htmlHelper.AntiForgeryToken().ToHtmlString();
        var beginIndex = field.IndexOf("value=\"") + 7;
        var endIndex = field.IndexOf("\"", beginIndex);
        return new HtmlString(field.Substring(beginIndex, endIndex - beginIndex));
    }
4b9b3361

Ответ 1

Возможности анти-CSRF MVC фактически зависят от двух токенов: один - скрытый элемент формы, а другой - файл cookie. Поэтому помощник Html.AntiForgeryToken() не просто возвращает фрагмент HTML. Он также имеет побочный эффект настройки этого файла cookie. Обратите внимание, что значение cookie и значение формы не равны, поскольку каждый из них кодирует разные фрагменты информации.

Если вы используете API AntiForgery.GetTokens, этот метод возвращает исходные токены вместо генерации фрагмента HTML. Параметры этого метода:

  • oldCookieToken: Если запрос уже содержит токен антивируса CSRF, укажите его здесь. Этот параметр может быть нулевым.
  • newCookieToken (параметр out): Если oldCookieToken был нулевым или не представлял действительный токен анти-CSRF файла cookie, этот параметр будет заполнен значением, которое вы должны поместить в файл cookie ответа. Если oldCookieToken представляет действительный токен анти-CSRF, тогда newCookieToken будет содержать null, когда метод вернется, и вам не нужно устанавливать файл cookie ответа.
  • formToken (параметр out): Этот параметр будет заполнен маркером, который должен присутствовать в теле формы при отправке обратно на сервер. Это значение, которое заканчивается тем, что оно завершается скрытым элементом ввода при вызове Html.AntiForgeryToken().

Если вы используете этот API для генерации маркеров файлов cookie и форм вручную, вам необходимо вызвать соответствующую перегрузку AntiForgery.Validate в порядке для проверки токенов.

Ответ 2

Я понимаю, что этот вопрос старый, но на основе того, что я читал здесь, я придумал достаточно простое решение, которое, похоже, работает для меня. Я использую его в AngularJS SPA, который использует частичные шаблоны, только некоторые из которых связаны с представлениями POST.

Я помещаю этот код в верхнюю часть представления:

@{
    string cookieToken, formToken;
    string oldCookieToken = Request.Cookies[AntiForgeryConfig.CookieName] == null ? null : Request.Cookies[AntiForgeryConfig.CookieName].Value;
AntiForgery.GetTokens( oldCookieToken, out cookieToken, out formToken );

    if( oldCookieToken == null ) 
    {
        Request.Cookies.Add( new HttpCookie( AntiForgeryConfig.CookieName,     cookieToken ) );
    }
    else 
    {
        Request.Cookies[AntiForgeryConfig.CookieName].Value = cookieToken;
    }
}

а затем везде, где мне нужен маркер antiforgery формы (например, в ajax или angularjs POST), я просто включаю '@formToken' в заголовки:

$http.post(route, JSON.stringify(args), {
     headers: {
        '@AntiForgeryConfig.CookieName':  '@formToken',
        'Content-Type': 'application/json; charset=utf-8',
     },
});

Обратите внимание, что, поскольку в этом примере я ожидаю, что данные JSON вернулись из моего метода действий, мне также пришлось внедрить проверку анти-подделки на основе заголовков, а не создавать поля. Там хорошая статья об этом на http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC.. Здесь реализация:

[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class,
                AllowMultiple = false, Inherited = true )]
public sealed class ValidateJsonAntiForgeryTokenAttribute
                            : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization( AuthorizationContext filterContext )
    {
        if( filterContext == null )
        {
            throw new ArgumentNullException( "filterContext" );
        }

        var httpContext = filterContext.HttpContext;
        var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
        AntiForgery.Validate( cookie != null ? cookie.Value : null,
                             httpContext.Request.Headers[AntiForgeryConfig.CookieName] );
    }
}

и здесь, как он используется:

    [HttpPost]
    [ValidateJsonAntiForgeryToken]
    public JsonResult RecordVisit( VisitInfo info )