4

我有 2 个网站,实际上它们是相同的。目的是其中一个是供互联网用户使用的,第二个是供本地使用的。现在它们托管在我的 localhost 机器上的同一个 IIS 服务器上。当我打开这两个网站并尝试获取标有 [ValidateAntiForgeryToken] 的操作结果时,我遇到了一个问题,即在我的 cookie 中,我的 localhost 站点有 cookie,并且有一个名为“ RequestVerificationToken_Lw ”的 cookie,它是防伪保护钥匙。问题在于两个站点都使用相同的 cookie 来存储此密钥。因此,如果在一个网站上做某事,当我尝试在另一个网站上做某事时,我会遇到防伪错误。

如何更改 cookie 域或任何其他解决方案来拆分 cookie?

谢谢你!

4

1 回答 1

0

好吧,让我们看看 ValidateAntiforgeryTokenAttribute 做了什么(Reflector/ILSpy 是你的朋友):

公共无效 OnAuthorization(AuthorizationContext filterContext)
{
    if (filterContext == null)
    {
        抛出新的 ArgumentNullException("filterContext");
    }
    字符串 antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(null);
    字符串 antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];
    if (httpCookie == null || string.IsNullOrEmpty(httpCookie.Value))
    {
        抛出 ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    AntiForgeryData antiForgeryData = this.Serializer.Deserialize(httpCookie.Value);
    字符串文本 = filterContext.HttpContext.Request.Form[antiForgeryTokenName];
    如果(字符串。IsNullOrEmpty(文本))
    {
        抛出 ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    AntiForgeryData antiForgeryData2 = this.Serializer.Deserialize(text);
    if (!string.Equals(antiForgeryData.Value, antiForgeryData2.Value, StringComparison.Ordinal))
    {
        抛出 ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    字符串用户名 = AntiForgeryData.GetUsername(filterContext.HttpContext.User);
    if (!string.Equals(antiForgeryData2.Username, username, StringComparison.OrdinalIgnoreCase))
    {
        抛出 ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
    if (!this.ValidateFormToken(antiForgeryData2))
    {
        抛出 ValidateAntiForgeryTokenAttribute.CreateValidationException();
    }
}

好的,很明显,令牌的 cookie 名称是由应用程序路径生成的:

    字符串 antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];

因此,您创建自己的过滤器,只需复制粘贴此代码,然后将其更改为也尊重端口(或根据您区分应用程序的任何内容):

    字符串 antiForgeryTokenName2 = AntiForgeryData.GetAntiForgeryTokenName(filterContext.HttpContext.Request.ApplicationPath + filterContext.HttpContext.Request.Url.Port);
    HttpCookie httpCookie = filterContext.HttpContext.Request.Cookies[antiForgeryTokenName2];

这样,cookie 名称(“RequestVerificationToken_Lw”)也会因端口而异。

当然,我们也不能忘记在创建令牌时更改此 cookie 名称。不幸的是,您需要在此处复制粘贴“重新实现”两件事 - 首先是 AntiForgeryToken 扩展方法来调用您自己的 AntiForgeryWorker,然后是 AntiForgeryWorker 本身 - 只需覆盖 GetAntiForgeryTokenAndSetCookie 方法,它与之前的内容相同:

字符串 antiForgeryTokenName = AntiForgeryData.GetAntiForgeryTokenName(httpContext.Request.ApplicationPath);

好吧,它看起来很乱,而且它绝对不是一个 DRY 解决方案,但如果你真的想要这个,你可以在几分钟内完成它。只需使用反射器和复制粘贴 :)

于 2011-10-25T11:38:15.843 回答