简体   繁体   English

我可以在不向客户端发送响应的情况下终止服务器上的HTTP事务吗?

[英]Can I Terminate HTTP transaction on server WITHOUT sending response to client?

I'm writing a public-facing transaction processor. 我正在写一个面向公众的交易处理器。 Naturally, we run on https:// and the payload carries all relevant detail so we'll only process legitimate transactions. 自然,我们在https://上运行,并且有效负载包含所有相关细节,因此我们将仅处理合法交易。 However, as a public interface, any number of nefarious actors will no doubt be throwing shade at my server if for no other reason than to just be annoying. 但是,作为公共接口,任何其他邪恶的行为者毫无疑问都将在我的服务器上蒙上阴影,除非是因为烦人而已。

When I detect such a request, is there anyway I can terminate processing at my end - not going to waste time on the transaction - but NOT send a response to the client? 当我检测到这样的请求时,是否仍然可以在结束时终止处理-不浪费时间在事务上-但不将响应发送给客户端? Basically, I'd like to force the nefarious clients into a timeout situation so that, if nothing else, it diminishes their capacity to annoy my server. 基本上,我想迫使邪恶的客户端进入超时状态,这样,即使没有别的事情,它也会减少它们烦扰我的服务器的能力。

Here's the code: 这是代码:

public class Webhook : IHttpModule
{
    /// <summary>
    /// You will need to configure this module in the Web.config file of your
    /// web and register it with IIS before being able to use it. For more information
    /// see the following link: http://go.microsoft.com/?linkid=8101007
    /// </summary>

    private bool m_sslRequired = false;

    #region IHttpModule Members
    <snip...>
    #endregion

    private void OnBeginRequest(object sender, EventArgs e)
    {
        WriteTrace("Begin OnBeginRequest");
        HttpContext ctx = HttpContext.Current;

        try
        {
            string processor = ctx.Request.Params["p"];
            if (processor != null && processor != "")
            {
                PluginProcessor(processor, ctx);
            }
        }
        catch (Exception ex)
        {
            ctx.Response.StatusCode = 500;
            ctx.Response.Write("ERROR");
        }

        ctx.ApplicationInstance.CompleteRequest();

        WriteTrace("End OnBeginRequest");
    }

    private void PluginProcessor(string processor, HttpContext ctx)
    {
        string pluginSpec = AppConfig.GetAppSetting(processor.Trim().ToLower());

        if (pluginSpec != "")
        {
            IWebhookProcessor proc = CreateProcessor(pluginSpec, ctx);
            proc.Process(ctx);
        }
    }

    private IWebhookProcessor CreateProcessor(string Processor, HttpContext ctx)
    {
        string assembly;
        string typeName;

        typeName = Processor.Substring(0, Processor.IndexOf(",")).Trim();
        assembly = Path.Combine(ctx.Request.PhysicalApplicationPath, "bin", Processor.Substring(Processor.IndexOf(",") + 1).Trim());

        var obj = Activator.CreateInstanceFrom(assembly, typeName);

        return (Interfaces.IWebhookProcessor)obj.Unwrap();
    }
}

So if the request doesn't map to a transaction handler, I'd like to 'hang' the client, but not in a way which will tie up resources on the server. 因此,如果请求未映射到事务处理程序,则我想“挂起”客户端,但不希望这种方式占用服务器资源。

Thanks for your advice! 谢谢你的建议!

I think the best thing you can do is use HttpRequest.Abort() , which doesn't leave the client hanging, but it does immediately sever the TCP connection. 我认为您可以做的最好的事情是使用HttpRequest.Abort() ,它不会使客户端挂起,但会立即切断TCP连接。 Even the docs say it is for this kind of scenario: 甚至文档都说它适用于这种情况:

You might use this method in response to an attack by a malicious HTTP client. 您可能会使用此方法来响应恶意HTTP客户端的攻击。

You would use it like this: 您可以这样使用它:

ctx.Request.Abort();

In a browser, you see a "connection reset" error. 在浏览器中,您会看到“连接重置”错误。

Another option is to send back an unexpected HTTP status, like 400, or my personal favourite, 418 . 另一种选择是发回意外的HTTP状态,例如400或我个人最喜欢的418

Update: If you reaaallly want to make the client wait, you could implement your own HttpModule so that you can make an asynchronous BeginRequest event and then use Task.Delay() . 更新:如果您完全想让客户端等待,则可以实现自己的HttpModule以便可以进行异步BeginRequest事件,然后使用Task.Delay()

The HttpModule class would look something like this: HttpModule类如下所示:

public class AsyncHttpModule : IHttpModule {
    public void Dispose() { }

    public void Init(HttpApplication app) {
        var wrapper = new EventHandlerTaskAsyncHelper(DoAsyncWork);
        app.AddOnBeginRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
    }

    private async Task DoAsyncWork(object sender, EventArgs e) {
        var app = (HttpApplication) sender;
        var ctx = app.Context;

        if (shouldDie) { //whatever your criteria is
            await Task.Delay(60000); //wait for one minute
            ctx.Request.Abort(); //kill the connection without replying
        }
    }
}

Then add the module in your web.config (replace the namespace with your app's namespace): 然后将模块添加到您的web.config中(用应用程序的名称空间替换名称空间):

<system.webServer>
  <modules>
    <add name="AsyncHttpModule" type="MyNamespace.AsyncHttpModule" />
  </modules>
</system.webServer>

Since this is asynchronous, it is not holding up a thread while it waits. 由于这是异步的,因此它在等待时不会占用线程。 Other requests that come in will use the same thread (I tested this). 传入的其他请求将使用相同的线程(我对此进行了测试)。

However, it is still keeping the request context in memory, because the request is still in progress. 但是,由于请求仍在进行中,因此它仍将请求上下文保留在内存中。 So if they hit you with 1000+ requests, all of those 1000+ requests are held in memory for 60 seconds. 因此,如果他们用1000多个请求打了你,那么所有1000多个请求都会在内存中保留60秒钟。 Whereas if you just use HttpRequest.Abort() right away, those get removed from memory right away. 而如果您只是立即使用HttpRequest.Abort() ,则会立即将其从内存中删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在没有客户端/服务器解决方案的情况下以局域网发送文件 - Sending file in lan without a client/server solution 向服务器发送 http 请求而不期待响应 - Send http request to server without expecting a response 通过c#服务发送服务器时间作为对HTTP GET的响应 - Sending the server time as a response to HTTP GET via c# service C#简单HTTP服务器未将响应发送到浏览器 - C# Simple HTTP Server not sending response to browser 使用HTTP格式向客户端/服务器发送XML消息 - Using http format in sending XML message to client/server 创建一个事务以将数据发送到服务器 - Create a transaction for sending data to the server 为什么我可以使用FileSystemObjects读取和写入客户端二进制文件,而不能读取和发送它们到服务器? - Why can I use FileSystemObjects for reading and writing client-side binary files, but not for reading and sending them to the server? 如何将HTTP响应发送回用户,但之后仍在服务器上执行更多操作? - How can I send the HTTP response back to the user but still do more things on the server after that? 服务器返回HTTP 401时,如何在WCF中获取消息/响应正文? - How can I get the message/response body in WCF when server returns an HTTP 401? 服务器响应为:5.7.1使用SMTP客户端发送电子邮件时未对客户端进行身份验证 - The server response was: 5.7.1 Client was not authenticated While Sending email using SMTP client
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM