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

Для чего используется XsrfKey, и должен ли я установить XsrfId на что-то еще?

В моем веб-приложении MVC 5 у меня есть это (в AccountController.cs):

    // Used for XSRF protection when adding external sign ins
    private const string XsrfKey = "XsrfId";

и

        public string SocialAccountProvider { get; set; }
        public string RedirectUri { get; set; }
        public string UserId { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
            if (UserId != null)
            {
                properties.Dictionary[XsrfKey] = UserId;
            }

            context.HttpContext.GetOwinContext().Authentication.Challenge(properties, SocialAccountProvider);
        }

Как именно он используется для защиты?

Должен ли я установить значение XsrfKey на что-то более случайное?

4b9b3361

Ответ 1

Взгляните на методы ManageController LinkLogin и LinkLoginCallback:

    //
    // POST: /Manage/LinkLogin
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LinkLogin(string provider)
    {
        // Request a redirect to the external login provider to link a login for the current user
        return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId());
    }

    //
    // GET: /Manage/LinkLoginCallback
    public async Task<ActionResult> LinkLoginCallback()
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
        if (loginInfo == null)
        {
            return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
        }
        var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
        return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
    }

Это методы, которые обрабатывают связывание внешних учетных записей (например, Google, Facebook и т.д.). Поток выглядит следующим образом:

  • Пользователь нажимает кнопку "Ссылка на учетную запись", которая вызывает метод POST до LinkLogin.
  • LinkLogin возвращает объект ChallengeResult, с URL-адресом обратного вызова, установленным в LinkLoginCallback.
  • ChallengeResult.ExecuteResult вызывается инфраструктурой MVC, вызывает IAuthenticationManager.Challenge, что вызывает перенаправление к определенному внешнему провайдеру входа (скажем: google).
  • Пользователь аутентифицируется с помощью Google, затем переадресовывает Google на URL-адрес обратного вызова.
  • Обратный вызов обрабатывается с помощью LinkLoginCallback. Здесь мы хотим предотвратить XSRF и убедиться, что вызов был инициирован пользователем, со страницы, обслуживаемой нашим сервером (а не каким-то вредоносным сайтом).

Обычно, если это была простая последовательность GET-POST, вы должны добавить скрытое поле <input> с токеном анти-подделки и сравнить его с соответствующим значением cookie (что как Асп. Интенсивные токены).

Здесь запрос поступает от внешнего поставщика авторизации (google в нашем примере). Поэтому нам нужно предоставить токен анти-подделки Google, а google должен включить его в запрос обратного вызова. То, что параметр состояния в OAuth2 был разработан для.

Вернемся к нашему XsrfKey: все, что вы помещаете в AuthenticationProperties.Dictionary, будет сериализовано и включено в параметр state запроса OAuth2 - и, следовательно, обратный вызов OAuth2. Теперь GetExternalLoginInfoAsync(this IAuthenticationManager manager, string xsrfKey, string expectedValue) будет искать XsrfKey в полученном состоянии Словарь и сравнить его с expectedValue. Он вернет ExternalLoginInfo, только если значения равны.

Итак, отвечая на ваш первоначальный вопрос: вы можете установить XsrfKey на все, что хотите, до тех пор, пока один и тот же ключ используется при настройке и чтении. Не имеет смысла устанавливать что-либо случайное - параметр state зашифрован, поэтому никто не ожидает, что вы все равно сможете его прочитать.

Ответ 2

Просто оставьте это как есть:

В качестве имени состояний-членов это ключ:

private const string XsrfKey = "XsrfId";

Определяется таким образом, чтобы избежать "магических чисел", а затем используется немного в коде эшафота:

public override void ExecuteResult(ControllerContext context)
{
    var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
    if (UserId != null)
    {
        properties.Dictionary[XsrfKey] = UserId;
    }
    context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}

Значение элемента словаря затем устанавливается в свойство UserId в приведенном выше коде с использованием члена XsrfKey в качестве ключа.

IOW код уже устанавливает элемент словаря XSRF в значение идентификатора пользователя в фрагменте. Если вы измените значение членов XsrfKey на что-либо еще, вы вызовете проблемы в строке, так как ожидаемый ключ "XsrfId" не будет установлен.

Если, изменив его на что-то более случайное, вы подразумеваете изменение значения, а не ключ из словаря, или, другими словами, не установите его в идентификатор пользователя, то, пожалуйста, посмотрите следующее для объяснения анти-подлога токены.

http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages