首页 > 解决方案 > 防伪令牌问题:不是在登录或注销时,而是在从支付处理器返回网站时

问题描述

我遇到了似乎无法正确调试的最奇怪的问题。

当前的项目:

当用户登录时,他们可以退出并重新登录而不会出现任何问题。那里没有令牌问题。超时时间为 60 分钟。

然而,在这个网站上有一个“购物车”,用户可以把一些非常有限的东西放进去并付费。付款按钮将它们移至付款处理器(托管的付款页面),然后由后者获取 CC 信息并处理该付款。付款完成(或失败)后,用户将被转回网站上的特定页面,也在他们的帐户中。这个登录页面唯一要做的就是查找支付处理器添加到 URL 末尾的一些 GET 值,并将这些值记录到数据库中(从而将购物车中的项目记录为已付款)。

然而,大约三分之一从支付处理商退回的人——在成功支付后——正在经历

提供的防伪令牌适用于与当前用户不同的基于声明的用户。

错误信息。

所以要清楚:

我在这个登陆页面上的代码非常简单:

[HttpGet]
public async Task<ActionResult> Processed() {
  var responseCode = Request.QueryString["RESPONSECODE"];
  var orderId = Request.QueryString["ORDERID"];
  var customField = HelperExtensions.GetGuid(Request.QueryString["CUSTOMFIELD1"]);
  var amount = Convert.ToDecimal(Request.QueryString["AMOUNT"]);
  var cardNumber = Request.QueryString["CARDNUMBER"];
  var approvalCode = Request.QueryString["APPROVALCODE"];
  var uniqueRef = Request.QueryString["UNIQUEREF"];
  var dateTime = Convert.ToDateTime(Request.QueryString["DATETIME"]);
  if(string.Equals(responseCode, "A")) { // Transaction approved
    //Process these values and insert them into the DB to mark the cart as having been paid.
  }
  //Send *everyone* to the View, with appropriate messages served up by the view’s model depending on the responseCode.
  return View("Processed", new ProcessedViewModel(transactionId, responseCode, orderId, amount, cardNumber, approvalCode, uniqueRef, dateTime, additionalErrors));
}

我已经尝试使用网站上的虚拟帐户验证这一点,并手动生成着陆页可以“处理”的返回 URL,但除非我愿意自己支付数千美元的 CC 费用(这些是会员费,在几百美元的范围内),我无法进行完整的往返旅行。

请注意,此问题在登录或注销期间明确出现。或者在注销后立即登录。它在用户从支付处理器返回到登录页面后才会显示。

另外请记住:三分之二的用户没有遇到此错误。只有大约三分之一是。所以这似乎是一个暂时的问题,我还没有找到着陆页上成功捕获和失败捕获之间的差异。

我什至用以下方式装饰所有控制器:

[NoCache]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]

第一个是我在 StackOverflow 其他地方找到的无缓存属性:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class NoCacheAttribute : ActionFilterAttribute {
  public override void OnResultExecuting(ResultExecutingContext filterContext) {
    filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
    filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
    filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
    filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    filterContext.HttpContext.Response.Cache.SetNoStore();

    base.OnResultExecuting(filterContext);
  }
}

尽管有这个添加,错误并没有停止(尽管还没有足够的付款来确定令牌错误的比率是否已经改变)。

标签: asp.netasp.net-mvcasp.net-mvc-5

解决方案


防伪令牌与 cookie 一起使用,如果 Web 浏览器阻止 cookie,则会导致此错误。

“提供的防伪令牌适用于与当前用户不同的基于声明的用户。”

创建一个操作来记录被阻止的 cookie,以便与存在此问题的用户进行比较。

假设您让客户离开网站进行支付并在没有 cookie 的情况下返回用户帐户,则防伪令牌可以防止 CSRF。

创建自定义防伪令牌,以便在禁用浏览器 cookie 时,令牌将存储在会话中并与会话进行比较。

看看这个网站

希望这可以帮助


推荐阅读