У меня есть веб-сайт MVC с некоторыми компонентами AngularJS.
Когда я делаю запрос на публикацию с помощью angularjs, я всегда включаю токен __RequestVerificationToken
со скрытого ввода на странице.
Моя проблема заключается в следующем:
Пользователь запускает анонимный сеанс, т.е. не вошел в систему.
Пользователь входит в систему, используя компонент angularjs, который отправляет запрос на публикацию.Мой контроллер MVC проверяет учетные данные и '__RequestVerificationToken'.Как только пользователь вошел в систему, он возвращает новый токен.
Затем контроллер angularjs берет новый токен и обновляет скрытый ввод, который будет использоваться для любых будущих запросов.
Однако следующийзапрос, который я использую с помощью angularjs, не проходит проверку, потому что var tokenCookie = filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName);
(см. пример кода ниже) все еще является старым токеном от анонимного сеанса.
Хотя «X-XSRF-Token» (см. пример кода ниже)приходит как новый.
Как мне также обновить / обновить файл cookie http (tokenCookie), содержащий токен, на новый?
Я разместил копию своего кода ниже.
Мой фильтр действий:
public sealed class WebApiValidateAntiForgeryTokenAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var headers = filterContext.HttpContext.Request.Headers;
var tokenCookie = filterContext.HttpContext.Request.Cookies.Get(AntiForgeryConfig.CookieName);
var tokenHeader = string.Empty;
if (headers.AllKeys.Contains("X-XSRF-Token"))
{
tokenHeader = headers.GetValues("X-XSRF-Token").FirstOrDefault();
}
AntiForgery.Validate(tokenCookie != null ? tokenCookie.Value : null, tokenHeader);
base.OnActionExecuting(filterContext);
}
}
Мой контроллер входа в систему:
[WebApiValidateAntiForgeryTokenAttribute]
[HttpPost]
public ActionResult login(string email, string password)
{
if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(password)) return new HttpUnauthorizedResult();
var rq = HttpContext.Request;
var r = validateLogin(email, password, true); // my login handling
if (r.Success)
{
Response.StatusCode = (int)HttpStatusCode.OK;
// within an action construct AJAX response and pass updated token to client
return Json(new
{
__RequestVerificationToken = UpdateRequestVerificationToken(Request)
});
}
else
{
return new HttpUnauthorizedResult();
}
}
/// <summary>
/// resets AntiForgery validation token and update a cookie
/// The new antiforgery cookie is set as the results and sent
/// back to client with Ajax
/// </summary>
/// <param name="Request">request from current context</param>
/// <returns>string - a form token to pass to AJAX response</returns>
private string UpdateRequestVerificationToken(HttpRequestBase Request)
{
string formToken;
string cookieToken;
const string __RequestVerificationToken = "__RequestVerificationToken";
AntiForgery.GetTokens(Request.Form[__RequestVerificationToken], out cookieToken, out formToken);
if (Request.Cookies.AllKeys.Contains(__RequestVerificationToken))
{
HttpCookie cookie = Request.Cookies[__RequestVerificationToken];
cookie.HttpOnly = true;
cookie.Name = __RequestVerificationToken;
cookie.Value = cookieToken;
Response.Cookies.Add(cookie);
}
return formToken;
}
Мой angularjs Обработка входа:
login(email, password) {
return new Promise((resolve, reject) => {
return this.AccountRequest.login(email, password)
.then(response => {
const newToken = response.data['__RequestVerificationToken'];
const oldTokenElement = angular.element('input[name="__RequestVerificationToken"]');
oldTokenElement.val(newToken); // confirmed the new token has been updated in the hidden element
resolve(this.refresh.bind(this));
});
})
}
Каждый раз, когда я делаюпочтовый запрос с использованием angularjs:
post(uri, queryParams = {}, data = null) {
this.$http.defaults.headers.common['X-XSRF-Token'] = angular.element('input[name="__RequestVerificationToken"]').attr('value');
this.$http.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; // Needed to ensure we get back http error instead of a webpage
const config = this.makeConfig('POST', uri, queryParams, data);
return this.$http(config);
}
makeConfig(method, uri, params = {}, data = null) {
return {
method,
data,
params,
url: uri.toString(),
};
}