zoukankan      html  css  js  c++  java
  • 浅谈ASP.NET的内部机制(一)

    前言:当一个Http请求发送给一个aspx页面时,服务器进行了哪些操作?又如何来解析这个请求?ASP.NET在接收请求后是怎么运行的,如怎么编译以及怎么样用托管的代码来运行的?.....理解这些问题,使我们可以更加好的开发ASP.NET。

    1.当我们在浏览器中请求一个ASP.NET网站的某个页面的时候,如,我们在浏览器中输入"http://localhost/Demo.aspx",这个请求就被发送到了服务器(当然了,这个网站是部署在IIS中的)。当请求到达了服务器之后,那么IIS就开始进行一系列的操作。注意,不是每个请求都一定会由ASP.NET来运行处理的,大家稍后就会明白为什么。

    2.在IIS中有一个组件:http.sys,其实这个组件的作用很简单,就是验证请求的url,如之前的"http://localhost/Demo.aspx".如果请求的URL不符合http.sys的要求,那么这个请求就不会被传递给ASP.NET的处理程序,这样就在IIS这道门槛这些阻止了不合法的url请求,这样ASP.NET就不用处理这个不合法的请求,就减轻了服务器的压力。


    下面,我们就来看看这个http.sys到底是怎么样处理请求的url的,当大家明白这个问题后,就可以帮助我们解决很多的以前遇到的问题。
    首先请大家看看下面的图:


    当发送一个请求来请求页面的时候,http.sys就会检查这个请求的url和headers的总的大小:包含检查url中有关查询字符串的大小,如demo.aspx?username=demo,也会检查cookie的大小。把这些所有的加起来,看看它们是否超过了16KB,如果超过了,请求就失败了。所以请求根本就没有传递给ASP.NET。

    而且在http.sys检查url的时候也有很多的要求的。如我们之前的那个url:
    http://localhost/Demo.aspx


    这个url是由localhost,Demo.aspx,这些路径的片段组成的,每一个由"/"分割的字符串都是一个路径片段,本例中就有两个路径片段。在默认情况下,http.sys要求一个url的路径片段不超过255个,并且每个路径片段的大小也不要超过260个字母。但是注意,如果在Demo.aspx后面有查询字符串,"Demo.aspx?page=1",那么这个片段就可以超过260个字母的限制,即"Demo.aspx?page=1"可以更大。但是不管怎么样,这些url的大小,如之前所说的,不能超过16KB。如果没有通过http.sys的要求,IIS就发送一个404的错误。

    之前也说了的,那是默认的这只,其实这些设置我们是可以在注册表中改的。但是默认设置已经很不错了,所以一般没有必要改。

    3.当请求的url通过了http.sys的检查后,请求就会传递给aspnet_filter.dll,下面简称filter。
    其实这个filter做两件事:将url中的无cookie的票据转换为Http Headers;保护ASP.NET的相应的目录。

    首先来看看第一个作用:检查url中的无cookie信息,并且转换为Http Headers.


    大家应该明白ASP.NET2.0中的新特性-支持无cookie,即cookieless。因为我们在进行验证的时候一般是基于Forms验证,而这种验证方式是把信息保存在cookie中的,但是有的用户的浏览器是禁用了cookie的,所以为了使得我们可以继续用这个验证方式,就把验证信息保存为无cookie,大家可以去查看有关这方面的资料。来看看下面的一个url:
    http://localhost/demo/(S(tuucni55xfzj2xqx1mnqdg55))/Default.aspx
    我们其实把有关的信息存储在了url中,如上面的"S"就标识在后面括号"()"的信息就是无cookie的信息(tuucni55xfzj2xqx1mnqdg55).
    来看看“S”是什么:
    S—Cookieless ticket for session state
    A—Cookieless ticket for anonymous identification
    F—Cookieless ticket for forms authentication


    其实filter并不知道这些标识(如"S")的意义.只是filter检查url中是否包含这些标识,并且这些标识后面还有"()",如果在url中检查到有这些标识,那么filter就把这些标识转换为Http Headers,并且在url中删除这些标识。我们本来请求的是http://localhost/demo/Default.aspx页面,但是如果filter不删除标识,那么我们请求的http://localhost/demo/(S(tuucni55xfzj2xqx1mnqdg55))/Default.aspx是不存在的,就会返回一个404错误(找不到请求的文件)。

    现在我们来看看filter的第二个作用的:保护ASP.NET的相应的目录。
    在我们开发的ASP.MET网站中,有很多的文件目录是不允许访问的,如我们存放数据的App_Data,App_Code等。所以filter就会检查请求的url中是否包含这样的字符,如http://localhost/demo/App_Code/....一旦发现有这样的字符串出现,甚至是以"App_"开发的任何字符串,如“App_MyFolder",这个请求就会被拒绝了。但是,假如你的项目中已经有一个这样的以"App_"命名的目录,如果你非要可以访问这样的目录,可以在注册表中修改设置HKEY_LOCAL_MACHINE\Software\Microsoft\ASP.NET。

    大家知不知道,一个Http Request是如何被传递给ASP.NET的?而且ASP.NET是如何知道一个 Http Request是请求的.aspx这样的动态文件还是请求的.htm这样的静态文件?......

      上次已经说到了http.sys和aspnet_filter的功能,希望大家还记得!

      当一个请求(也就是http Request)通过了http.sys和aspnet_fitler后,此时这个请求还没有被传递给ASP.NET的处理程序。但是此时IIS就会在它的MIME Type中查找请求文件的处理程序。

      其实MIME Type不神秘,就是注册了哪些文件由哪些组件来处理。大家看看下面的图就明白了。

    浅谈ASP.NET的内部机制(二)

      大家应该对上面的图很熟悉。而IIS就是通过查找上面的那个表来决定一个请求到底请求的是那种文件,如果是静态的文件,如htm,那么这个请求就直接由IIS来处理了,也不会传递给ASP.NET处理程序。如果请求的文件是.aspx或者.asmx等,那么IIS就知道请求是就传递给aspnet_isapi.dll的,随后就启动一个进程来加载这个dll,随后就开始进行一系列的初始化工作,然后就把请求传递给ASP.NET。

      下面我们就来详细的看看,在真正处理一个请求的时候,到底进行了哪些的初始化操作。

      1.当IIS知道了处理的是.aspx的文件后,就启动一个进程w3wp.exe来开始运行ASP.NET。

      2.因为此时aspnet_isapi.dll已经加载运行了,而且aspnet_isapi.dll是一个用托管代码编写的组件,而所有的托管代码都要运行在应用程序域(Application Domain,以后我们简称Domain)中,所以进行加载后,首先就是建立一个Domain。因为我们请求的是一个ASP.NET中的一个页面,而且这个页面是属于一个用ASP.NET开发的网站,所以这个网站就是一个应用程序,要在Domain中运行的。但是建立一个Domain要经过很多的步骤的。(注:大家也许认为没有必要把建立Domain的步骤弄清楚,但是我认为很有必要,因为在建立一个Domain的过程中,涉及到很多的ASP.NET的内部问题,而且这个问题在实际开发中也很重要,如ASP.NET运行时的权限和可信域(与安全问题相关),也涉及代码安全等,还可以帮助我们理解代码的编译).

     下面就来说说建立一个Domain的步骤:

      2.1 为一个Domain建立标识;

      2.2 验证访问的文件目录是否存在,并且初始化目录的信息

      2.3 设置Domain的信任级别

      2.4 设置程序集的位置

      2.5 得到自动生成的机器码

      2.6 初始化ASP.NET编译系统

      首先,我们来看看 为一个Domain建立标识。

      因为一个应用程序是运行在服务器的硬盘上的,所以在运行的时候必须有一个标识(identity),其实标识就是运行程序的用户名和ID,这是操作系统要的。在IIS6中,一个ASP.NET程序就是以NT AUTHORITYNETWORK SERVICE的身份来运行的。因为不同的identity对系统的操作权限不同,我们可以在配置文件,如web.config中配置别的权限,使得我们的程序可以进行更多的操作(如写入文件,读取系统注册表等),只要配置<identity />。

      其次,我们来看看 验证访问的文件目录是否存在,并且初始化目录的信息。

      一个ASP.NET网站的由很多的文件组成的。如果我们请求的的文件在这个网站中没有或者我们没有读取那个文件的权限,那么就会产生从服务器返回错误的信息。

      而且ASP.NET还会初始化一些目录的信息,如在App_Data中的文件,因为.Net Framework2.0以后的版本,ADO.NET的还会自己的把数据文件与Sql Server相连,并且建立连接。

      最后就是还会决定一个ASP.NET的网站的自动产生的代码回放在哪里。比如我们请求一个Default.aspx页面,这个页面还有一个.cs文件,在我们请求时,这两个文件会生成一个继承Page的类,所以ASP.NET必须决定这个生成的文件放在哪里。

      然后,我们来看看 设置Domain的信任级别。

      其实一个Domain的信任级别就决定了这个Domain可以做哪些事情。也就是一个Domain的权限有多大。

      主要有:1.Enterprise 2. Machine 3. User 4. Application domain。

      其实这也是一个代码访问安全的问题(code access security (CAS)).就是说,这个Domain中的应用程序的代码可以执行的操作的权限。比如,如果Domain的信任级别很大,甚至程序中的代码可以访问Windows API。

      我们可以在调用System.AppDomain.CurrentDomain.SetAppDomainPolicy,来设置级别。

      再次,我们来看看 设置程序集的位置。

      上面的一些步骤就已经建立了一个Domain的安全策略,一个Domain中运行的网站一般会有一些程序集的,而且位于bin目录下,还有之前提过的自动的类也会会被编译为程序集,.NET Framework会监管这些程序集。

      再后,我们来看看 得到自动生成的机器码。

      其实机器码就是machineKey,每个应用程序在运行的时候,都会有machineKey,一般是ASP.NET随机生成的,但是我们也可以自动的制定,在web.config的<machineKey />中制定。这个功能很有用的,比如你有几个服务器,或者几个不同的网站,我们希望在一台服务器上的网站登录后,然后我们在其他的服务器的网站上去的时候,我们就可以是已经登录用户。也就是可以实现"一次登录,到处可用"。

      最后,就是 初始化ASP.NET编译系统。

      这时就编译程序集,并且解析其中的类,,而且还解析app_webreferences的目录和global.asax。程序开始运行了,也有了Application的实例来主导整个应用。

  • 相关阅读:
    html+vue.js 实现分页可兼容IE
    Display、Visibility 和 Opacity 的区别
    Vue项目刷新页面 IE/360 浏览器 input输入框不清空问题处理
    Webpack入门
    linux下Tomcat日志文件catalina.out的切割
    无监控,不运维
    windows与linux下jdk+tomcat安裝
    java面向对象(提高篇)
    java面向对象(汇总)
    JAVA工程师简历模板
  • 原文地址:https://www.cnblogs.com/JiaHu/p/1552150.html
Copyright © 2011-2022 走看看