asp.net - 防伪令牌问题:不是在登录或注销时,而是在从支付处理器返回网站时
问题描述
我遇到了似乎无法正确调试的最奇怪的问题。
当前的项目:
- ASP.NET 4.7.2
- MVC 5
当用户登录时,他们可以退出并重新登录而不会出现任何问题。那里没有令牌问题。超时时间为 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);
}
}
尽管有这个添加,错误并没有停止(尽管还没有足够的付款来确定令牌错误的比率是否已经改变)。
解决方案
防伪令牌与 cookie 一起使用,如果 Web 浏览器阻止 cookie,则会导致此错误。
“提供的防伪令牌适用于与当前用户不同的基于声明的用户。”
创建一个操作来记录被阻止的 cookie,以便与存在此问题的用户进行比较。
假设您让客户离开网站进行支付并在没有 cookie 的情况下返回用户帐户,则防伪令牌可以防止 CSRF。
创建自定义防伪令牌,以便在禁用浏览器 cookie 时,令牌将存储在会话中并与会话进行比较。
看看这个网站。
希望这可以帮助
推荐阅读
- java - 如何获取 ListView 项的 ID 而不是列表视图上的位置?
- r-markdown - R降价和定制包
- android - 转义房间数据库查询中的特殊字符
- nearprotocol - 如何从对智能合约的调用中返回一个值?
- python - 使用 keras 在各个层上应用卷积
- excel - Excel - 将行单元格转换为逗号分隔列表
- android - 解密在 Android 中加密的 Dart 中的文本
- r - 如何使用 rpresto 通过 https 连接到数据库?
- tomcat - IIS ARR:禁用或覆盖转发请求中附加的“X-Original-URL”HTTP 标头
- javascript - 打包时如何在 Electron 应用中管理文件?