我如何使用自定义IHttpModule和HttpRequest过滤器来修改POST请求?

概观

我希望能够将请求参数和内容修改为第三方Web服务(ArcGIS Server)。 这将用于创建存在于任何客户端应用程序和服务器应用程序之间的安全层。

我认为我已经找到了解决方案,但我目前在实施中遇到了一些困难。

潜在的解决方案:使用自定义请求过滤器修改请求

对于解决方案,我基于MSDN上显示的示例松散地实现了自定义请求过滤器。 我已经'增强'了代码,以便我可以使用正则表达式来搜索和替换必要的内容。 这包括:

  • 将内容(存储在字节数组中)转换为字符串。
  • 搜索字符串并执行任何必要的修改。
  • 将修改后的字符串转换为字节数组并将其写入缓冲区。
  • 一个例子如下所示:

    public override int Read(byte[] buffer, int offset, int count)
    {
        int bytesRead = _stream.Read(buffer, offset, count);
    
        string orgContent = Encoding.UTF8.GetString(buffer, offset, bytesRead);
        string orgContentDecoded = HttpUtility.UrlDecode(orgContent);
    
        string layersPattern = @"&layers=(show|hide|include|exclude):([0-9]+,?)+";
        Regex layersRegex = new Regex(layersPattern, RegexOptions.IgnoreCase);
    
        string[] permittedLayers = new string[] { "0" , "1" };
        string replacementLayers = "&layers=show:" + String.Join(",", permittedLayers);
        string newContentDecoded = layersRegex.Replace(orgContentDecoded, replacementLayers);
    
        string newContent =  newContentDecoded.Replace(",", "%2C").Replace(":", "%3A");
    
        byte[] newBuffer = Encoding.UTF8.GetBytes(newContent);
        int newByteCountLength = Encoding.UTF8.GetByteCount(newContent);
    
        Encoding.UTF8.GetBytes(newContent, 0, Encoding.UTF8.GetByteCount(newContent), buffer, 0);
    
        return bytesRead;
    }
    

    只要修改的内容长度与原始内容长度没有差异,这似乎工作得很好。 例如,如果我用1代替1,那么一切正常。 但是,如果我用10替换1(从而将消息大小增加1),那么我会从ArcGIS Server收到格式不受支持的错误。

    这引起了我的两个关注:

  • 当前的实现不处理分块的请求。 也就是说,如果请求sie足够大,则对于单个请求可能会多次调用Read。 在这种情况下应该如何处理chunking?
  • 错误信息的根源是什么? 与内容长度相关的问题是否与流长度不同? 如何正确修改内容以便更改其长度不是问题?
  • 有什么想法吗?


    这个问题的第二部分的答案是返回修改后的内容大小,而不是原始流的大小。 看哪!

    // return bytesRead;
    return newByteCountLength;
    

    这个问题和你的答案对我来说真的很有用,但是如果你试图向流中插入大量数据,答案并不是全部。

    只有当您插入流中的数据不会占用通过count数值读入缓冲区的字节数时,才返回修改的内容大小。 如果尝试插入太多数据,您要么发现buffer对象不够大,无法保存要插入的数据,要么通过将多个count字节写入缓冲区来覆盖缓冲区末尾的一些数据本来应该放在一边。

    如果您需要插入比当前buffer对象容纳的更多数据,那么您必须将数据缓存在单独的字节数组中,并在调用stream.read将其复制为块。


    正如Chris McKeown所说,除非您保证不修改数据大小,否则这不是真正的过滤技术。 为了完整回答这个问题,我发布了一个示例项目,演示如何处理过滤请求和响应使用缓冲技术,如果你有兴趣。

    https://github.com/snives/HttpModuleRewrite

    也有关排除HttpModules过滤这篇文章的问题也很有帮助是否可以修改IIS HttpModule中的HttpRequest POST的内容?

    链接地址: http://www.djcxy.com/p/7601.html

    上一篇: How can I modify a POST request using a custom IHttpModule and an HttpRequest filter?

    下一篇: Mixing Active Records with Standard SQL Query in Codeigniter