ASP.Net请求处理机制初步探索之旅 - Part 2 核心

开篇:上一篇我们了解了一个请求从客户端发出到服务端接收并转到ASP.Net处理入口的过程,这篇我们开始探索ASP.Net的核心处理部分,借助强大的反编译工具,我们会看到几个熟悉又陌生的名词(类):HttpRuntime、HttpWorkerRequest、HttpContext、HttpApplication等。

(1)Part 1:前奏

(2)Part 2:核心

(3)Part 3:管道

(4)Part 4:WebForm页面生命周期

(5)Part 5:MVC页面声命周期

一、第一个入口:ISAPIRuntme.ProcessRequest()

  ISAPIRuntime是进入NET托管环境的入口,它在方法中通过一个ecb句柄指向了当前请求报文体的内存地址,将HTTP请求报文简单封装为一个HttpWorkerRequest对象,然后就是各种我们经常听到的PR(ProcessRequest)方法了。

①调用ISAPIRuntime对象的ProcessRequest方法进入ASP.NET处理流程

  通过Reflector,我们可以看到在ISAPIRuntime中的这个入口方法:ProcessRequest

②首先根据ecb句柄创建HttpWorkerRequest对象封装原始请求报文

关于HttpWorkerRequest:

在Asp.Net中准备用于处理的请求,都必须封装为HttpWorkerRequest类型的对象,HttpWorkerRequest是一个抽象类型。这里创建的是一个ISAPIWorkerRequest类型,它继承于HttpWorkerRequest类。

复制代码

[ComVisible(false)]
public abstract class HttpWorkerRequest
{// Fieldsprivate DateTime _startTime;private Guid _traceId;......
}

复制代码

  转到ISAPIWorkerRequest类的CreateWorkerRequest方法中,看到首先判断当前IIS服务器的版本(IIS6 or IIS7?),然后创建适合不同IIS的具体WorkerRequest对象,默认都是InProc进程内的,当然,也有OutOfProc进程外的。

复制代码

internal static ISAPIWorkerRequest CreateWorkerRequest(IntPtr ecb, bool useOOP)
{if (useOOP){EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);if (EtwTrace.IsTraceEnabled(5, 1)){EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, false);}return new ISAPIWorkerRequestOutOfProc(ecb);}int num = UnsafeNativeMethods.EcbGetVersion(ecb) >> 0x10;if (num >= 7){EtwTrace.TraceEnableCheck(EtwTraceConfigType.IIS7_ISAPI, ecb);}else{EtwTrace.TraceEnableCheck(EtwTraceConfigType.DOWNLEVEL, IntPtr.Zero);}if (EtwTrace.IsTraceEnabled(5, 1)){EtwTrace.Trace(EtwTraceType.ETW_TYPE_APPDOMAIN_ENTER, ecb, Thread.GetDomain().FriendlyName, null, true);}if (num >= 7){return new ISAPIWorkerRequestInProcForIIS7(ecb);}if (num == 6){return new ISAPIWorkerRequestInProcForIIS6(ecb);}return new ISAPIWorkerRequestInProc(ecb);
}

复制代码

  由于HttpWorkerRequest类封装的请求报文很原始,很复杂,所以微软没有将其公开出来。

二、第二个入口:HttpRuntime.ProcessRequest()

  HttpRuntime是ASP.NET请求处理的第二个入口。当请求进来,首先进入HttpRuntime,由HttpRuntime来决定如何处理请求。默认情况下,在machine.config和Web.config中并没有显式定义httpRuntime节点,但该节点是有默认值的,如下:

复制代码

<httpRuntime apartmentThreading="false"appRequestQueueLimit="5000"delayNotificationTimeout="5"enable="true"enableHeaderChecking="true"enableKernelOutputCache="true"enableVersionHeader="true"encoderType = "System.Web.Util.HttpEncoder"executionTimeout="110"maxQueryStringLength = "2048"maxRequestLength="4096"maxUrlLength = "260"maxWaitChangeNotification="0"minFreeThreads="8"minLocalRequestFreeThreads="4"relaxedUrlToFileSystemMapping = "False"requestLengthDiskThreshold="80"requestPathInvalidCharacters = "<,>,*,%,&,:,\"requestValidationMode = "4.0"requestValidationType = "System.Web.Util.RequestValidator"requireRootedSaveAsPath="true"sendCacheControlHeader="true"shutdownTimeout="90"useFullyQualifiedRedirectUrl="false"waitChangeNotification="0" />

复制代码

  通常情况下,我们可以在Web.config中更改httpRuntime节点的默认值,如下:

复制代码

<configuration><system.web><httpRuntime maxRequestLength="4000"enable = "True"requestLengthDiskThreshold="512useFullyQualifiedRedirectUrl="True"executionTimeout="45"versionHeader="1.1.4128"/></system.web>
</configuration>

复制代码

①其次执行HttpRuntime的ProcessRequestNoDemand方法封装HttpContext对象

  在HttpRuntime类中,有一个称为ProcessRequestNoDemand的静态方法。这里创建并初始化HttpWorkerRequest对象后,调用了HttpRuntime的这个ProcessRequestNoDemand方法。于是,我们转到ProcessRequestNoDemand方法,可以看到如下代码:

复制代码

internal static void ProcessRequestNoDemand(HttpWorkerRequest wr)
{RequestQueue queue = _theRuntime._requestQueue;wr.UpdateInitialCounters();if (queue != null){wr = queue.GetRequestToExecute(wr);}if (wr != null){CalculateWaitTimeAndUpdatePerfCounter(wr);wr.ResetStartTime();ProcessRequestNow(wr);}
}

复制代码

  该方法先从请求队列中取出一个请求,然后更新请求的引用计数器的信息,然后再将HttpWorkerRequest对象传入ProcessRequestNow方法来处理请求。

  这里我们还可以看到_theRuntime这个字段,它是HttpRuntime类的一个静态字段,在HttpRuntime的静态构造函数中进行初始化。

复制代码

public sealed class HttpRuntime
{// Fields......private static HttpRuntime _theRuntime;......
}

复制代码

  再回到ProcessRequestNoDemand方法中,我们看到最后是由ProcessRequestNow方法来接棒。于是,我们转到ProcessRequestNow方法再来看看:

internal static void ProcessRequestNow(HttpWorkerRequest wr)
{_theRuntime.ProcessRequestInternal(wr);
}

  我们看到在这个方法中又调用了_theRuntime的实例方法:ProcessRequestInternal,还是把HttpWorkerRequest对象作为参数传递了过去。于是,我们再转到ProcessRequestInternal这个方法中,发现了一个重要的对象:HttpContext对象。

复制代码

private void ProcessRequestInternal(HttpWorkerRequest wr)
{Interlocked.Increment(ref this._activeRequestCount);if (this._disposingHttpRuntime){......}else{HttpContext context;try{context = new HttpContext(wr, false);}catch{try{wr.SendStatus(400, "Bad Request");wr.SendKnownResponseHeader(12, "text/html; charset=utf-8");byte[] data = Encoding.ASCII.GetBytes("<html><body>Bad Request</body></html>");wr.SendResponseFromMemory(data, data.Length);wr.FlushResponse(true);wr.EndOfRequest();return;}finally{Interlocked.Decrement(ref this._activeRequestCount);}}...... }
}

复制代码

  在HttpContext的构造函数中,根据HttpWorkerRequest对象创建了HttpContext对象,这是一个重要的Http上下文对象,两个重要类型的字段也随之被初始化:HttpRequest对象和HttpResponse对象。

  相信大家在进行ASP.NET开发时,经常使用这两个类型的实例。例如,我们可以通过HttpContext.Current获取到这个实例,且该实例会在整个生命周期中存活,我们通过它可以获取到一些常用对象,如Request,Response,Session 等。

②通过HttpApplicationFactory得到一个具体的HttpApplication实例

  让我们再次回到HttpRuntimeProcessRequestInternal这个方法中,刚刚HttpContext对象被创建后,紧接着又干了什么事?让我们看看源码:

复制代码

private void ProcessRequestInternal(HttpWorkerRequest wr)
{Interlocked.Increment(ref this._activeRequestCount);if (this._disposingHttpRuntime){......}else{HttpContext context;...... IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);......if (applicationInstance is IHttpAsyncHandler){IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;context.AsyncAppHandler = handler2;handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);}else{applicationInstance.ProcessRequest(context);this.FinishRequest(context.WorkerRequest, context, null);}...... }
}

复制代码

   首先,我们看到了一个非常熟悉的字眼:IHttpHandler,我们的ashx、aspx不都是实现了这个IHttpHandler接口的吗?于是,我们来看看这句:IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context); 它是通过一个叫做HttpApplicationFactory的工厂类来获取了一个HttpApplication的实例,并将HttpContext上下文对象作为参数传递了进去。于是,怀着好奇心,我们转到这个方法内部去看看:

复制代码

internal static IHttpHandler GetApplicationInstance(HttpContext context)
{......
    _theApplicationFactory.EnsureInited();_theApplicationFactory.EnsureAppStartCalled(context);
    return _theApplicationFactory.GetNormalApplicationInstance(context); 
}

复制代码

  原来,它是调用了一个实例方法:GetNormalApplicationInstance来获取HttpApplication。于是,我们再转到这个方法的内部去看看:

复制代码

private HttpApplication GetNormalApplicationInstance(HttpContext context)
{HttpApplication state = null;lock (this._freeList){if (this._numFreeAppInstances > 0){state = (HttpApplication) this._freeList.Pop();this._numFreeAppInstances--;if (this._numFreeAppInstances < this._minFreeAppInstances){this._minFreeAppInstances = this._numFreeAppInstances;}}}if (state == null){state = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType);using (new ApplicationImpersonationContext()){state.InitInternal(context, this._state, this._eventHandlerMethods);}}......return state;
}

复制代码

  通过查看这段代码,它首先维护着一个HttpApplication池(_freeList,本质上就是一个Stack栈),然后判断可用的HttpApplication实例的数量(_numFreeAppInstances)是否大于0?如果存在可用的,则从池中出栈,然后将可用数量减1。最后,再判断可用的数量是否小于最低限制的数量,如果小于那么则将最低限制的数量设置为目前可用的数量。

HttpApplication Pool

  那么,如果目前HttpApplication池暂时没有可用的实例呢?我们看到了这一句:state = (HttpApplication) HttpRuntime.CreateNonPublicInstance(this._theApplicationType); 通过此段代码,新建了一个新的HttpApplication实例,通过继续深入查看,原来是通过反射的方式将Global文件所编译后的类封装出来一个HttpApplication实例。

补充之一:_theApplicationType是_theApplicationFactory.EnsureInited();中被赋值的

private void CompileApplication()
{this._theApplicationType = BuildManager.GetGlobalAsaxType();......
}

补充之二:全局事件中例如Application_Start方法如何保证只执行一次?在_theApplicationFactory.EnsureAppStartCalled(context);方法中,判断_appOnStartCalled标志,如果是false则调用FireApplicationOnStart方法触发Application_Start方法,然后更改_appOnStartCalled标志。

复制代码

private void EnsureAppStartCalled(HttpContext context)
{if (!this._appOnStartCalled){lock (this){if (!this._appOnStartCalled){using (new DisposableHttpContextWrapper(context)){......this.FireApplicationOnStart(context);}this._appOnStartCalled = true;}}}
}

复制代码

三、第三个入口:HttpApplication.Init()

  在前两个入口中,HttpApplication实例被创建,现在HttpApplication需要进行初始化请求处理管道,来分别处理ASP.Net WebForm或ASP.Net MVC等类型的页面的响应操作。

①初始化HttpModules

  让我们再次回到HttpRuntime的ProcessRequestInternal这个方法中,刚刚HttpApplication实例被创建后,开始了一系列的初始化操作,如下图所示,调用了其InitInternal方法进行了初始化。

  转到InitInternal方法内部,发现调用了一个非常重要的方法:InitModules()。

复制代码

internal void InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
{this._state = state;PerfCounters.IncrementCounter(AppPerfCounter.PIPELINES);try{......this.InitModules();......if (HttpRuntime.UseIntegratedPipeline){this._stepManager = new PipelineStepManager(this);}else{
        this._stepManager = new ApplicationStepManager(this);
      }this._stepManager.BuildSteps(this._resumeStepsWaitCallback);
   } catch { ...... } 
}

复制代码

  在InitModules这个方法中,首先通过读取Web.config配置文件中关于HttpModule的信息,然后将其传递给HttpModule的集合,如下代码所示:

复制代码

private void InitModules()
{HttpModuleCollection modules = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();HttpModuleCollection other = this.CreateDynamicModules();modules.AppendCollection(other);this._moduleCollection = modules;this.InitModulesCommon();
}

复制代码

  然后,调用InitModulesCommon方法,遍历上面这个_moduleCollection集合,分别对其每一个HttpModule执行其对应的Init方法。

复制代码

private void InitModulesCommon()
{int count = this._moduleCollection.Count;for (int i = 0; i < count; i++){this._currentModuleCollectionKey = this._moduleCollection.GetKey(i);this._moduleCollection[i].Init(this);}this._currentModuleCollectionKey = null;this.InitAppLevelCulture();
}

复制代码

注册19个请求处理管道事件

  接上述操作之后,InitInternal方法内部还执行了这样一句:this._stepManager.BuildSteps(this._resumeStepsWaitCallback); 它完成了19个请求处理管道事件的注册工作。

复制代码

internal override void BuildSteps(WaitCallback stepCallback)
{ArrayList steps = new ArrayList();HttpApplication app = base._application;bool flag = false;UrlMappingsSection urlMappings = RuntimeConfig.GetConfig().UrlMappings;flag = urlMappings.IsEnabled && (urlMappings.UrlMappings.Count > 0);steps.Add(new HttpApplication.ValidateRequestExecutionStep(app));steps.Add(new HttpApplication.ValidatePathExecutionStep(app));if (flag){steps.Add(new HttpApplication.UrlMappingsExecutionStep(app));}/* 以下代码完成19个事件的注册 */app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);steps.Add(new HttpApplication.MapHandlerExecutionStep(app));app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);steps.Add(app.CreateImplicitAsyncPreloadExecutionStep());steps.Add(new HttpApplication.CallHandlerExecutionStep(app));app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);steps.Add(new HttpApplication.CallFilterExecutionStep(app));app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);this._endRequestStepIndex = steps.Count;app.CreateEventExecutionSteps(HttpApplication.EventEndRequest, steps);steps.Add(new HttpApplication.NoopExecutionStep());this._execSteps = new HttpApplication.IExecutionStep[steps.Count];steps.CopyTo(this._execSteps);this._resumeStepsWaitCallback = stepCallback;
}

复制代码

  从上面的代码可知,ApplicationStepManager对象的BuildSteps方法被调用,完成HttpApplication 19个管道事件的注册。这个方法很重要,它将创建各种HttpApplication.IExecutionStep保存到一个数组列表 _execSteps 中:

复制代码

internal override void BuildSteps(WaitCallback stepCallback)
{.....this._execSteps = new HttpApplication.IExecutionStep[steps.Count];steps.CopyTo(this._execSteps);.....
}

复制代码

  这样做的目的在于:便于在后面的BeginProcessRequest方法内部调用ResumeSteps方法依次执行这些对象的Execute()方法,完成各个事件的执行。 

③开始依次处理请求处理管道中的各个事件

  让我们再返回到HttpRuntime中的ProcessRequestInternal方法中,HttpApplication实例已创建好,HttpModules已初始化,请求处理管道中的19个事件也已经注册好,现在需要的只是一一调用HttpModule中各个事件对应的执行方法即可。

复制代码

private void ProcessRequestInternal(HttpWorkerRequest wr)
{......if (applicationInstance is IHttpAsyncHandler){IHttpAsyncHandler handler2 = (IHttpAsyncHandler) applicationInstance;context.AsyncAppHandler = handler2;handler2.BeginProcessRequest(context, this._handlerCompletionCallback, context);}......
}

复制代码

  在上述代码中,通过执行BeginProcessRequest方法,触发了ResumeSteps方法依次执行每个请求处理管道事件,也就进入了我们所说的“请求处理管道”中。

复制代码

IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{this._context = context;this._context.ApplicationInstance = this;this._stepManager.InitRequest();this._context.Root();HttpAsyncResult result = new HttpAsyncResult(cb, extraData);this.AsyncResult = result;if (this._context.TraceIsEnabled){HttpRuntime.Profile.StartRequest(this._context);}
    // 依次执行各个请求处理管道事件this.ResumeSteps(null); return result; 
}

复制代码

关于请求处理管道:

HttpApplication 采用处理管道的方法进行处理,将处理的过程分成多个步骤,每个步骤通过事件的形式暴露给程序员,这些事件按照固定的处理顺序依次触发,程序员通过编写事件处理方法就可以自定义每一个请求的扩展处理过程。

对于 HttpApplication 来说,到 ASP.NET 4.0 版本,提供了19 个标准事件,如下图所示:

  至于在请求处理管道中的细节,我们在Part 3中再看,今天就到此为止,谢谢!

四、核心过程总览

①ISAPIRuntime->HttpWorkerRequest->HttpRuntime

1

②HttpRuntime->HttpContext->HttpApplication

2

③到目前为止的总体流程概览

  • 首先,我们从自己的浏览器通过网络访问Web服务器
  • 当ASP.NET接收到第一个请求时,将会创建一个应用程序域,然后会创建一个宿主环境
  • 然后ASP.NET创建并初始化核心对象HttpContext、HttpRequest和HttpResponse
  • 然后创建HttpApplication对象的实例来启动应用程序
  • 通过进入请求处理管道来处理具体的请求

参考资料

(1)Darren Ji,《ASP.NET MVC请求处理管道声明周期的19个关键环节》:http://www.cnblogs.com/darrenji/p/3795661.html

(2)木宛城主,《ASP.NET那点不为人知的事儿》:http://www.cnblogs.com/OceanEyes/archive/2012/08/13/aspnetEssential-1.html

(3)Tony He,《ASP.NET请求处理机制》:http://www.cnblogs.com/cilence/archive/2012/05/28/2520712.html

(4)两会的博客,《IIS是怎样处理ASP.NET请求的》:http://www.cnblogs.com/hkncd/archive/2012/03/23/2413917.html

(5)wjn2000,《ASP.NET请求处理过程(IIS6)》:http://www.cnblogs.com/wjn2010/archive/2011/04/21/2024341.html

(6)农村出来的大学生,《ASP.NET网页请求处理全过程(反编译)》:http://www.cnblogs.com/poorpan/archive/2011/09/25/2190308.html

 

作者:周旭龙

出处:http://edisonchou.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

REVERSE-COMPETITION-0xGame2021

REVERSE-COMPETITION-0xGame2021Signin: User FriendlyInstallerOur Compilation StoryPacketRandom ChaosNeverlandRoundaboutDespacitoSecret BaseMazeZero ThreeMirrorThread_TLS茶谈室JunkertownSignin: User Friendly 64位exe&#xff0c;ida打开&#xff0c;在main函数中…

ASP.Net请求处理机制初步探索之旅 - Part 3 管道

开篇&#xff1a;上一篇我们了解了一个ASP.Net页面请求的核心处理入口&#xff0c;它经历了三个重要的入口&#xff0c;分别是&#xff1a;ISAPIRuntime.ProcessRequest()、HttpRuntime.ProcessRequest()以及HttpApplication.Init()。其中&#xff0c;在HttpApplication的Init(…

PWN-COMPETITION-GeekChallenge2021

PWN-COMPETITION-GeekChallenge2021check in恋爱小游戏ret2xxone恋爱小游戏2.0easyfmteasycanaryret2babypwn777check in 66s内解答200道四则运算的题目即可getshell 参与运算的数和运算符都会打印&#xff0c;直接写脚本即可 # -*- coding:utf-8 -*- from pwn import * cont…

ASP.Net请求处理机制初步探索之旅 - Part 4 WebForm页面生命周期

开篇&#xff1a;上一篇我们了解了所谓的请求处理管道&#xff0c;在众多的事件中微软开放了19个重要的事件给我们&#xff0c;我们可以注入一些自定义的业务逻辑实现应用的个性化设计。本篇&#xff0c;我们来看看WebForm模式下的页面生命周期。 &#xff08;1&#xff09;Par…

REVERSE-COMPETITION-GeekChallenge2021

REVERSE-COMPETITION-GeekChallenge2021Re0刘壮桌面美化大师买ActivityRe1调试珍惜生命new_languageeasypycBrute_forcewin32wasm猜拳have_a_teaRe0 64位exe&#xff0c;ida打开&#xff0c;main函数中没发现什么重要的逻辑 ShiftF12打开字符串窗口&#xff0c;直接找到flag明…

ASP.Net请求处理机制初步探索之旅 - Part 5 ASP.Net MVC请求处理流程

开篇&#xff1a;上一篇我们了解了在WebForm模式下一个Page页面的生命周期&#xff0c;它经历了初始化Init、加载Load以及呈现Render三个重要阶段&#xff0c;其中构造了页面控件树&#xff0c;并对页面控件树进行了大量的递归操作&#xff0c;最后将与模板结合生成的HTML返回给…

REVERSE-PRACTICE-CTFSHOW-6

REVERSE-PRACTICE-CTFSHOW-6真的是签到批量生产的伪劣产品来一个派森snake真的是签到 附件是一个压缩包&#xff0c;解压需要密码&#xff0c;但是题目没有给到解压密码 实际上是压缩包伪加密&#xff0c;将如图橙色处原本的字节0x09改为0x00&#xff0c;保存后即可解压出文件…

REVERSE-PRACTICE-CTFSHOW-7

REVERSE-PRACTICE-CTFSHOW-7签层饼Tea_tube_poteasy贪吃蛇的秘密签层饼 32位exe&#xff0c;ida打开 main函数中&#xff0c;输入两个大于0的数字&#xff0c;如果flag_num为0&#xff0c;则将两个输入作为flag的一部分&#xff0c;打印flag 选中input_1按x查找交叉引用&…

HttpModule与HttpHandler详解(转)

ASP.NET对请求处理的过程&#xff1a; 当请求一个*.aspx文件的时候&#xff0c;这个请求会被inetinfo.exe进程截获&#xff0c;它判断文件的后缀&#xff08;aspx&#xff09;之后&#xff0c;将这个请求转交给 ASPNET_ISAPI.dll&#xff0c;ASPNET_ISAPI.dll会通过http管道&am…

Windows 系统中 Python下 Pygame 的安装

Pygame是跨平台Python模块&#xff0c;专为电子游戏设计&#xff0c;可用于管理图形、动画乃至声音&#xff0c;建立在SDL基础上&#xff0c;允许实时电子游戏研发而无需被低级语言&#xff08;如机器语言和汇编语言&#xff09;束缚&#xff0c;通过使用Pygame来处理在屏幕上绘…

REVERSE-PRACTICE-CTFSHOW-8

REVERSE-PRACTICE-CTFSHOW-8Matara OkinaanniuwarmupeMatara Okina apk文件&#xff0c;jadx-gui打开 MainActivity什么都没有&#xff0c;来到FlagActivity scheme&#xff0c;host这些看不懂 第44行有个ans和bytes的比较&#xff0c;ans已知&#xff0c;bytes是从某个地方获…

Html控件和Web控件(转)

作为一名ASP.NET的初学者&#xff0c;了解并且区别一些混淆概念是很必须的&#xff0c;今天这篇博文 就是主要向大家介绍一下Html控件和Web控件。在ASP.net中&#xff0c;用户界面控件主要就是 Html控件和Web控件&#xff0c;在前台页面上看&#xff0c;两种控件非常相似&…

VMware Pro 14 安装 Ubuntu 18.04 详细教程

目录● 安装步骤1.下载安装 VMware Workstation Pro 142.下载 Ubuntu 18.04 系统3.在 VMware 中创建虚拟机4.在虚拟机上安装 Ubuntu 系统● 安装过程中可能会出现的一些问题 1.在虚拟机上安装 Ubuntu 系统的过程中卡死不动 2.Ubuntu 不能全屏显示● 安装步骤 1.下载安装 VMware…

Web服务器控件和HTML控件的区别与联系

我们知道&#xff0c;在ASP.NET中&#xff0c;使用了两类控件&#xff0c;一类是HTML控件&#xff0c;还有一类是WEB控件。 WEB控件我们已经很熟悉&#xff0c;因为它是ASP.NET提供&#xff0c;一般关于ASP.NET的教程文章都会仔细介绍这些控件的详细应用技巧&#xff1b; 而H…

Hexo 博客优化之博客美化系列(持续更新)

2022-01-25 更新&#xff1a;博客新地址&#xff1a;https://www.itbob.cn/&#xff0c;文章距上次编辑时间较远&#xff0c;部分内容可能已经过时&#xff01; 本文将讲述一些 Hexo 博客的美化&#xff0c;本文以作者 luuman 的 spfk 主题和作者 xaoxuu 的 Material X 主题为例…

一台电脑部署两个或多个 Hexo 博客(一台电脑使用两个或多个 GitHub 账号)

由于个人原因需要在一台电脑上部署两个Hexo博客&#xff0c;本来以为挺简单&#xff0c;没想到问题重重&#xff0c;首先是一个GitHub账号只能搭建一个Hexo博客&#xff0c;因此就需要使用其他GitHub账号&#xff1b;其次是一台电脑绑定两个GitHub账号&#xff0c;则需要两对公…

element.style内联样式修改

最近在修改我个人博客的一个样式时发现&#xff0c;无论我如何修改style里面的值&#xff0c;页面上的样式都不会被修改&#xff0c;F12检查一下发现个element.style&#xff0c;但是却找不到这个值在哪里&#xff0c;查资料后才知道element.style为内联样式&#xff0c;基本很…

免费CDN:jsDelivr+Github 使用方法

CDN的全称是Content Delivery Network&#xff0c;即内容分发网络。CDN是构建在网络之上的内容分发网络&#xff0c;依靠部署在各地的边缘服务器&#xff0c;通过中心平台的负载均衡、内容分发、调度等功能模块&#xff0c;使用户就近获取所需内容&#xff0c;降低网络拥塞&…

EasyUI学习总结(一)——EasyUI入门

一、EasyUI下载 EasyUI官方下载地址&#xff1a;http://www.jeasyui.com/download/index.php&#xff0c;目前最新的版本是&#xff1a;jQuery EasyUI 1.4.1 下载完成之后&#xff0c;得到压缩包&#xff0c;解压后&#xff0c;得到一个【jquery-easyui-1.4.1】文件夹&#xff…

PWN-PRACTICE-CTFSHOW-1

PWN-PRACTICE-CTFSHOW-1PWN签到题pwn02pwn03pwn04PWN签到题 nc连上去就会打印flag pwn02 栈溢出&#xff0c;覆盖返回地址为后门函数stack起始地址即可 # -*- coding:utf-8 -*- from pwn import * #ioprocess("./pwn1") ioremote("pwn.challenge.ctf.show&…