Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 正在修补Asp.net Mvc2 AntiForgeryToken异常_Asp.net Mvc_Asp.net Mvc 2_Reflection_Patch_Antiforgerytoken - Fatal编程技术网

Asp.net mvc 正在修补Asp.net Mvc2 AntiForgeryToken异常

Asp.net mvc 正在修补Asp.net Mvc2 AntiForgeryToken异常,asp.net-mvc,asp.net-mvc-2,reflection,patch,antiforgerytoken,Asp.net Mvc,Asp.net Mvc 2,Reflection,Patch,Antiforgerytoken,我的问题的一些背景: Mvc2中似乎存在与ValidateAntiForgeryTokenAttribute有关的更改/错误 从Mvc1升级到Mvc2时,具有活动会话的用户在使用ValidateAntiForgeryTokenAttribute请求页面时将收到以下错误: 无法将“System.Web.UI.Triplet”类型的对象强制转换为“System.object[]”类型 该问题已记录在案 升级到Mvc2后,我们预计我们将受到此问题的严重影响。我已经从注释中的代码中编写了一个修复程序(以

我的问题的一些背景:

Mvc2中似乎存在与
ValidateAntiForgeryTokenAttribute
有关的更改/错误

从Mvc1升级到Mvc2时,具有活动会话的用户在使用
ValidateAntiForgeryTokenAttribute
请求页面时将收到以下错误:

无法将“System.Web.UI.Triplet”类型的对象强制转换为“System.object[]”类型

该问题已记录在案

升级到Mvc2后,我们预计我们将受到此问题的严重影响。我已经从注释中的代码中编写了一个修复程序(以下为子孙后代提供了文档)。此时,通过创建
Controller
AsyncController
的子类来调用此代码,以重写Initialize方法来纠正问题。e、 g

public class FixedController:Controller
{
    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);
        this.FixAntiForgeryTokenMvc1ToMvc2(requestContext); //extension
    }
}

internal static class ControllerEx
{
    public static void FixAntiForgeryTokenMvc1ToMvc2(
        this Controller controller,
        RequestContext requestContext)
    {
        var cc = new ControllerContext(requestContext,
                                       controller);
        var antiForgeryAttribute = new ValidateAntiForgeryTokenAttribute();
        try
        {
            antiForgeryAttribute.OnAuthorization(new AuthorizationContext(cc));
        }
        catch (HttpAntiForgeryException forgeryException)
        {
            var castException = forgeryException.InnerException;
            if (castException != null
                && castException is InvalidCastException
                && castException.Message.StartsWith(
                       "Unable to cast object of type"
                       + " 'System.Web.UI.Triplet' to type"
                       + " 'System.Object[]'"))
            {
                var responseTokenCookieNames =
                    controller
                        .Response
                        .Cookies
                        .Cast<Cookie>()
                        .Select(c => c.Name)
                        .Where(n => n.Contains("RequestVerificationToken"));
                foreach (var s in responseTokenCookieNames)
                {
                    var cookie = controller.Response.Cookies[s];
                    if (cookie != null)
                    {
                        cookie.Value = "";
                    }
                }
                var requestTokenCookieNames =
                    controller
                        .Request
                        .Cookies
                        .Cast<String>()
                        .Where(n => n.Contains("RequestVerificationToken"))
                        .ToList();
                foreach (var c in requestTokenCookieNames)
                {
                    controller.Request.Cookies.Remove(c);
                }
            }
        }
    }
}
公共类固定控制器:控制器
{
受保护的覆盖无效初始化(RequestContext RequestContext)
{
初始化(requestContext);
this.FixAntiForgeryTokenMvc1ToMvc2(requestContext);//扩展名
}
}
内部静态类控制器REX
{
公共静态无效固定AntiforgeryTokenMVC1TOMVC2(
这个控制器,
请求上下文(RequestContext)
{
var cc=新的ControllerContext(requestContext,
控制器);
var antiForgeryAttribute=new ValidateAntiForgeryTokenAttribute();
尝试
{
antiForgeryAttribute.OnAuthorization(新授权上下文(cc));
}
捕获(HttpAntiforyException伪造异常)
{
var castException=forgeryException.InnerException;
如果(castException!=null
&&castException是无效的castException
&&castException.Message.StartWith(
“无法强制转换类型为的对象”
+“'System.Web.UI.Triplet'以键入”
+“'System.Object[]”)
{
var响应Kencookienames=
控制器
.答复
.饼干
.Cast()
.选择(c=>c.Name)
其中(n=>n.Contains(“RequestVerificationToken”);
foreach(var s响应Kencookienames)
{
var cookie=controller.Response.Cookies[s];
if(cookie!=null)
{
cookie.Value=“”;
}
}
var requestTokenCookieNames=
控制器
要求
.饼干
.Cast()
其中(n=>n.Contains(“RequestVerificationToken”))
.ToList();
foreach(requestTokenCookieNames中的变量c)
{
controller.Request.Cookies.Remove(c);
}
}
}
}
}
这样做的连锁反应是,我必须修改我的所有控制器类,以从新的、已更正的控制器子类派生。对于打算在大约一个月内弃用的代码来说,这似乎相当麻烦

所以,说到我的问题,我想知道是否有一种侵入性较小的方法来修补现有类,这样就不必修改类的下游用户,也许可以使用反射?

Spender

使用basecontroller并继承basecontroller,而不是对每个控制器进行编码,方法如下:

public abstract class BaseController : Controller
{
    protected override void Initialize(RequestContext requestContext)
    {
        base.Initialize(requestContext);
        FixAntiForgeryTokenMvc1ToMvc2(this, requestContext);
    }
    private static void FixAntiForgeryTokenMvc1ToMvc2(
        Controller controller, RequestContext requestContext)
    {
        // stuff ....
    }
}
在“普通”控制器中,只需:

public class NormalController : BaseController
{
    // all the previous stuff
}

试一试…

升级前你能断开所有人的连接吗?如果可能的话,我们不想这样做。我知道这对你的任务没有帮助。在大约3个月前进行类似升级之前,我们很幸运地通知所有用户清除他们的缓存/cookie。我兜圈子,试图找到解决潜在问题的可行办法。最后(这是一款只有50名用户的商业应用程序),我们通过电子邮件向他们发送了关于如何清除“碎片”的指示。当然,如果你的是一个公共网站,那么以上可能是唯一的行动方针。我将密切关注这一点,因为我对一些即将到来的工作感兴趣。此外,您可以使用basecontroller并让您的所有其他控制器继承它,从而只对其进行一次编码,然后在迁移完成后(比如说4个月内——或其他时间)从单个位置将其删除. 这将是我的第一个攻击角度(使用与你的OP类似的代码)@jim:我认为清除缓存和cookies是没有必要的。防伪令牌只是页面中的一个隐藏输入。当我们升级时,几乎没有任何问题;大多数出现错误的人只是重新加载了页面,然后就可以很好地提交了。这就是我目前的做法。它仍然需要更改所有控制器以从新的基础派生。好的-在这种情况下,对基础控制器的单个更改不会影响到从它继承的所有内容吗??。当然,我假设您“一直”有一个基础控制器,因此我的建议是随意的。否则的话,我想陪审团还没有出来:(当然……这正是计划,因此这些事情都得到了很好的控制。我真的很想知道是否有一种侵入性较小的方法来修补坏代码。除非有人说不一样,否则我很高兴我已经采取了最好的方法。斯宾德,伊姆霍,我想你已经采取了最为广泛理解的方法,因此我不会他最务实的态度毕竟是暂时的。