Взгляните на методы 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 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 и т. д.). Поток выглядит следующим образом:
LinkLogin
. LinkLogin
возвращает объект ChallengeResult
с URL-адресом обратного вызова, установленным в LinkLoginCallback
. ChallengeResult.ExecuteResult
вызывается каркасом MVC, вызывает IAuthenticationManager.Challenge
, что вызывает перенаправление к определенному внешнему провайдеру входа (скажем: google). LinkLoginCallback
. Здесь мы хотим предотвратить XSRF и убедиться, что вызов был инициирован пользователем, со страницы, обслуживаемой нашим сервером (а не каким-то вредоносным сайтом). Обычно, если это была простая последовательность GET-POST, вы бы добавили скрытое поле с токеном анти-подделки и сравните его с соответствующим значением cookie (вот как Asp.Net Anti-Forgery Tokens работает).
Здесь запрос поступает от внешнего поставщика авторизации (google в нашем примере). Поэтому нам нужно предоставить токен анти-подделки Google, а google должен включить его в запрос обратного вызова. Это точно, какой параметр состояния состояния для OAuth2 был разработан.
Вернемся к нашему XsrfKey
: все, что вы ввели AuthenticationProperties.Dictionary
, будет сериализовано и включено в параметр state
запроса OAuth2 - и, следовательно, обратного вызова OAuth2. Теперь GetExternalLoginInfoAsync(this IAuthenticationManager manager, string xsrfKey, string expectedValue)
будет искать XsrfKey
в полученном словаре состояния и сравнить его с expectedValue
. Он вернет значение ExternalLoginInfo
, только если значения равны.
Итак, отвечая на ваш исходный вопрос: вы можете установить XsrfKey
на все, что хотите, до тех пор, пока один и тот же ключ используется при настройке и прочитав его. Не имеет смысла указывать на что-либо случайное - параметр state
зашифрован, поэтому никто не ожидает, что вы все равно сможете его прочитать.