戈多

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  20 随笔 :: 2 文章 :: 1 评论 :: 1 引用

2010年7月12日 #

首先简单介绍下Page类

  在.NET Framework中,Page类提供了ASP.NET应用程序从.aspx文件开始创建的所有对象的基本行为。Page类在System.Web.UI命名空间中定义,它派生于TemplateControl类并实现了IHttpHandler接口。TemplateControl类是一个抽象类,它为 Page 类和 UserControl 类提供通用属性和方法。

  由于Page类派生于一个是实现了INamingContainer接口的类,Page类还充当它的所有组成控件的容器。一个控件命名容器实现了INamingContainer接口的第一个父控件。对于任何一个实现了命名容器接口的类,ASP.NET创建一个新的虚拟命名空间,其中保证所有的子控件在整个控件树有唯一的名称。通俗点INamingContainer接口无任何方法,知识保证其子控件有唯一的名称。

  Page类实现IHttpHandler接口的方法,从而可以充当一种特殊类型的HTTP请求(.aspx文件的请求)的处理程序。ASP.NET运行库调用ProcessRequest方法用来处理请求。

  在ASP.NET页面中,runat属性设置为server的任何控件都不能放在<form>标签外。那么是怎么做到确定所有控件不在form外的呢?可以用Page类的VerifyRederingInSeverForm()方法。控件在生成时调用该方法,以确保服务器窗体的主体包含它们。该方法不返回一个值,但是出错的情况下会抛出一个异常。

 

  在ASP.NET页面揭秘(一)中我们提到执行和触发ProcessRequest调用的步骤和事件过程统称为页面生存周期。其实HTTP运行库激活ProcessRequest时便开始执行页面,ProcessRequest启动页面并控制生命期

  页面生命期分三个阶段:建立阶段,回发阶段,结束阶段。每个阶段有一个或多个子阶段,并且有一个或多个事件和步骤引发组成。

一 页面的建立

  当HTTP运行库实例化页面类以便为当前提供服务时,页面构造器创建一个控件树。该控件树连接到页面解析器在查看ASPX源文件后所创建的实际类。处理请求开始时,应设置所有的子控件和页面本征特征(如HTTP上下文,请求对象和响应对象)。

  页面生命期第一步是确定为什么运行库正在处理页面请求。其中原因有多样:正常请求,回发,跨页回发或者回叫。页面对象根据具体原因配置内部状态,并根据请求方法(GET或POST)准备投递的值集合(post value)。这部完成后,页面就准备激发用户代码事件。

1.PreIntit事件

  它是页面生命周期进入点。该事件激发时,页面还没有关联任何的母版页和主题。页面滚动位置已经恢复,投递的数据可以用,并且所有的页面控件已经被实例化且默认地取ASPX源文件中定义的属性值(注意这时控件没有ID,除非在.aspx源文件中显式地设置它)只有这时才可以通过编程方式修改母版页或主题。该事件只有在页面上可用。IsCallBack(该值指示页请求是否是回调的结果),IsCrossPagePostback(获取一个值,该值指示跨页回发中是否涉及该页)和IsPostback(获取一个值,该值指示该页是否正为响应客户端回发而加载,或者它是否正被首次加载和访问)都在这时设置其值。

2.Init 事件

  这时已经设置母版页和主题,并且不能修改。页面处理器,即Page类上的ProcessRequest方法,遍历所有的子控件,使他们有机会以一种上下文相关的方法初始化它们的状态。所有的子控件递归地调用它们的OnInit方法。为控件集合中的每个控件设置命名容器和一个具体的ID。Init事件首先到达子控件,然后到达页面。这个阶段,页面和控件通常开始加载他们的部分状态。然而这时没有恢复视图状态。

3.IntiComplete事件

  这个只有页面才有的事件,表明初始化子阶段的结束。在Init 事件和IntiComplete事件之间只发生一个操作:打开视图状态变更的跟踪功能。它始终使控件能够真正地把所有以编程方式添加到ViewState结合中的数值持久地存储在存储介质中。即没有打开跟踪状态的控件,任何添加到ViewState的值将会在下一次回发时丢失。所有控件在发出Inti事件后立即打开视图状态跟踪,页面也不例外。

4.视图状态恢复

  如果页面由于回发处理,则恢复VIEWSTATE隐藏字段内容。_VIEWSTATE隐藏字段保存着一个请求结束时所有控件视图状态。页面的总体视图状态是一种调用上下文,包含页面最后一次服务器时每个组成控件的状态。(ViewState个可以留到控件相关的知识里介绍)

5.处理投递的数据

  HTTP请求中包装的所有用户数据,即用<form>标签定义的所有输入字段的内容,都在这时进行处理。投递的数据通常采取如下格式:

      TextBox1=text&DropDownList1=selectedItem&Button1=Submit

这是一串用&隔开的名称/值对。这些值装入一个内部使用的集合。页面处理器视图将投递的数据集合中的名称与页面中的控件的ID进行匹配。每找到一个匹配,处理器检查该服务器控件有没有实现 IPostBackDataHanlder接口。如果实现了,则调用该接口的LoadPostData方法,该控件有机会根据投递的数据刷新它的状态。具体说,如果LoadPostData()方法返回true,即状态已被更新,则把该控件添加到一个不同的集合中,以便以后引起关注。

(注:LoadPostData实现IPostBackDataHandler(实现控件数据回传必须要继承该接口)的一个方法,该方法参数NameValueCollection类型的对象装载了客户端提交的数据。另外该方法还会比较控件的旧值和新值返回一个bool类型值,以决定是否执行RaisePostDatachangedEvent方法,即跟新控件里的值,详细请看深入理解.net服务器控件

  如果一个发送的名称与任何一个服务器控件都不匹配,则留下它并临时放在一个不同的集合中,稍后再试。

6.PreLoad事件

  它指页面已经结束系统初级初始化阶段,并且准备进入下一个阶段,即还有机会在该页面中的用户代码中配置页面的执行和呈现。

7.Load事件

  首先它针对页面的引发,然后递归针对所有的子控件引发。页面中的控件在此时创建,并且他们的状态完全反映前一个状态以及从客户端发送的任何数据。页面准备执行所有与页面逻辑和行为有关的初始化代码。这时,访问控件属性和视图状态是绝对安全的。

8处理动态创建的控件

  如果在显示前,页面中的所有控件都有机会完成初始化,页面处理器将再次尝试匹配那些尚未与现有控件匹配的投递值。这主要是应对动态的创建的控件

设想把一个控件动态地添加到页面树上,例如为了响应某个用户动作。每次回发以后重新创建页面,因此与动态创建的控件有关的任何信息会丢失。另一方面,提交页面的窗体时,其中的动态控件定期发送的合法而有效地信息填充。根据设计,第一次投递的数据时,不可能有什么服务器控件匹配动态控件ID。然而,ASP.NET Fromework知道Load事件会创建某些控件。因此有了再次匹配这一说。如果动态控件已经在Load事件中被重建了,现在就可以找到一种匹配,并且该控件可以用投递的数据刷新状态。

 

二 处理回发

  回发机制它涉及到把窗体数据投递到相同页面,然后使用视图状态恢复调用上下文,在服务器上最后一次生成投递页时存在的控件的同一种状态。

  在页面初始化已经完成并已经考虑投递的值以后,会发生某些服务器端事件。事件类型主要有两种。

1.检测控件状态变化

  整个ASP.NET工作机制围绕一个隐含的假设:在浏览器中操作一些HTML输入标签与服务器控件具有一一对应关系。例:<input type=”text”>与<asp:TextBox>。当用户把一些信息输入到元素中后,调用对应的TextBox 控件来处理该投递值。

  对于让LoadPostData方法返回true的所有控件,现在要执行RaisePostDataChangeEvent方法,该方法也属于IPostBackDataHandler接口。该方法通知ASP.NET应用程序控件的状态已经发生变化。

2.执行服务器端回发事件

  任何回发都从某个打算触发一个服务器端动作的客户端动作开始。相信大家对回发事件应经很理解了这里不再多介绍。通俗的说就是能触发服务器端的事件代码的执行。

3.LoadComplete事件

  表明页面准备阶段的结束。任何子控件都不会接受该事件。激发LoadComplete页面进入呈现阶段。

 

三 页面结束

处理回发事件以后,页面准备为浏览器生成输出。

1.PreRender事件

  通过处理该事件,页面和控件可以在呈现输出之前任何更新。PreRender事件首先为页面激发,然后递归地为控件激发。

2.PreRenderConmplete事件

  因为PreRender事件是递归地为所有子控件激发的,所以编程者无法知道何时完成预呈现阶段。而该事件的激发代表上面的事件结束了。

3.SaveStateComple事件

  在每个控件生成页面的标记之前,把页面的当前状态保存到视图状态存储介质。在页面上的控件状态已经全部保存到持久性质时,会触发该事件。

4.生成标记

  为浏览器生成标记是通过调用各组成控件来生成自己的标记来完成的,这些标记将存储到一个缓冲区中。这个阶段没有任何用户事件。

5.Unload事件

  生成阶段之后是一个递归调用,为每个控件引发Unload事件,并最终为页面引发Unload事件。Unload事件存在的目的是在释放页面对象之前执行所有最后的清除工作。典型操作是关闭文件和数据库连接。

posted @ 2010-07-12 15:12 戈多 阅读(91) 评论(0) 编辑

2010年6月7日 #

泛化(Generalization

 

                                                                              

   

在上图中,空心的三角表示继承关系(类继承),在UML的术语中,这种关系被称为泛化(Generalization)。Person()是基类,Teacher(教师)Student(学生)Guest(来宾)是子类。

若在逻辑上BA的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。

例如,教师是人,Teacher Person的“一种”(a kind of )。那么类Teacher可以从类Person派生(继承)。

如果A是基类,BA的派生类,那么B将继承A的数据和函数。

如果类A和类B毫不相关,不可以为了使B的功能更多些而让B继承A的功能和属性。

若在逻辑上BA的“一种”(a kind of ),则允许B继承A的功能和属性。

聚合(组合)

                                                                       

 

  

若在逻辑上AB的“一部分”(a part of),则不允许BA派生,而是要用A和其它东西组合出B

例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head应该由类EyeNoseMouthEar组合而成,不是派生(继承)而成。

聚合的类型分为无、共享(聚合)、复合(组合)三类。

聚合(aggregation

                              

  

上面图中,有一个菱形(空心)表示聚合(aggregation)(聚合类型为共享),聚合的意义表示has-a关系。聚合是一种相对松散的关系,聚合类B不需要对被聚合的类A负责。

组合(composition)

                                                                  

  

 

这幅图与上面的唯一区别是菱形为实心的,它代表了一种更为坚固的关系——组合(composition)(聚合类型为复合)。组合表示的关系也是has-a,不过在这里,A的生命期受B控制。即A会随着B的创建而创建,随B的消亡而消亡。

依赖(Dependency)

                                                                  

 

   这里BA的关系只是一种依赖(Dependency)关系,这种关系表明,如果类A被修改,那么类B会受到影响。

   组合或是聚合,你得从思想上去判断,而不能从实现上判断,因为它们两个的实现,可能是及其接近的。


   首先要说明的是概念。《设计模式》一书中没有使用“组合”这个概念,而UML表示中一般没有使用“相识”这个概念。但是两者实际上存在如下的对应关系:
/////////////////////////////////////////////
《设计模式》 UML 表示的意义
聚合 组合 聚合/组合 对象和其所有者具有相同的生命周期
相识 聚合 一个对象仅仅知道另一个对象
/////////////////////////////////////////////
不过,这个对应关系也不是绝对的。

1、 UML中还有一种关系叫“关联”,《设计模式》中对这种关系的说明很准确:“OMT还定义了类间的关联(association)关系,以类间的一条线来表示。关联关系是双向的。虽然在分析阶段这种关系是适用的,但我们觉得它对于描述设计模式内的类关系来说显得太抽象了,因为在设计阶段关联关系必须被映射为对象引用或指针。对象引用本身就是有向的,更适合表达我们所讨论的那种关系。”也可以说“关联”到代码的映射是一对多的,并且这种一对多的关系会影响到模式的选择。
2、 UML中“组合”“聚合”的概念是用来表示对象的静态结构的,因此我们可以这样认为:“组合”就是用成员变量实现的,而“聚合”就是用指向某个对象的指针来实现的。当然,这里略去了对成员函数的参数的考虑。
3、 《设计模式》中对“聚合”和“相识”的关系描述如下:“C++中,聚合可以通过定义表示真正实例的成员变量来实现,但更通常的是将这些成员变量定义为实例指针或引用;相识也是以指针或引用来实现。”“从根本上讲,是聚合还是相识是由你的意图而不是由显式的语言机制决定的。”通过这两个说明,可以看到《设计模式》中认为“聚合”和“相识”关系是运行时的动态特性,从这点上来说和UML有本质的区别。另外,《设计模式》中对这两者动态特性描述如下:“聚合关系使用较少且比相识关系更持久;而相识关系则出现频率较高,但有时只存在于一个操作期间,相识也更具动态性,使得它在源代码中更难被辨别出来。”显然,这种描述只是说到了量的问题,而没有说到质的问题,从这里还是看不出“聚合”和“相识”到底在运行时有什么本质不同。

 

posted @ 2010-06-07 18:27 戈多 阅读(146) 评论(1) 编辑

2010年4月6日 #

为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用。本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本结构。对那些对WCF不是很了解的读者来说,这个例子将带领你正式进入WCF的世界。

在这个例子中,我们将实现一个简单的计算服务(CalculatorService),提供基本的加、减、乘、除的运算。和传统的分布式通信框架一样,WCF本质上提供一个跨进程、跨机器以致跨网络的服务调用。在本例中,客户端和服务通过运行在相同的同一台机器上不同进程模拟,图1体现了客户端和服务端进程互相调用的关系。

                                                               

                                                                                                         图1 计算服务应用运行环境

 

WCF的服务不能孤立地存在,需要寄宿于一个运行着的进程中,我们把承载WCF服务的进程称为宿主,为服务指定宿主的过程称为服务寄宿(Service Hosting)。在我们的计算服务应用中,采用了两种服务寄宿方式:通过自我寄宿(Self-Hosting)的方式创建一个控制台应用作为服务的宿主(寄宿进程为Hosting.exe);通过IIS寄宿方式将服务寄宿于IIS中(寄宿进程为IIS的工作进行W3wp.exe)。客户端通过另一个控制台应用模拟(进程为Client.exe)。接下来,我们就一步一步来构建这样的一个WCF应用。

步骤一:构建整个解决方案

通过VS 2008创建一个空白的解决方案,添加如下四个项目。项目的类型、承载的功能和相互引用关系如下,整个项目在VS下的结构如图2所示。

  • Contracts一个类库项目,定义服务契约(Service Contract),引用System.ServiceMode程序集(WCF框架的绝大部分实现和API定义在该程序集中);
  • Services一个类库项目,提供对WCF服务的实现。定义在该项目中的所有WCF服务实现了定义在Contracts中相应的服务契约,所以Services具有对Contracts项目的引用;
  • Hosting一个控制台(Console)应用,实现对定义在Services项目中的服务的寄宿,该项目须要同时引用Contracts和Services两个项目和System.ServiceMode程序集;
  • Client一个控制台应用模拟服务的客户端,该项目引用System.ServiceMode程序集。

                                                          

                                                                                               图2 计算服务在VS中的结构

 

 

步骤二:创建服务契约

WCF采用基于契约的交互方式实现了服务的自治,以及客户端和服务端之间的松耦合。WCF包含四种类型的契约:服务契约、数据契约、消息契约和错误契约,这里着重于服务契约。从功能上讲,服务契约抽象了服务提供的所有操作;而站在消息交换的角度来看,服务契约则定义了基于服务调用的消息交换过程中,请求消息和回复消息的结构,以及采用的消息交换模式。第4章将提供对服务契约的详细介绍。

一般地,我们通过接口的形式定义服务契约。通过下面的代码,将一个接口ICalculator定义成服务契约。WCF广泛采用基于自定义特性(Custom Attribtue)的声明式编程模式,我们通过在接口上应用System.ServiceModel.ServiceContractAttribute特性将一个接口定义成服务契约。在应用ServiceContractAttribute特性的同时,还可以指定服务契约的名称和命名空间。至于契约名称和命名空间的含义和作用,在本人拙著《WCF技术剖析(卷1)》第4章,在这里我们将契约名称和命名空间设置成CalculatorService和http://www.artech.com/)。

通过应用ServiceContractAttribute特性将接口定义成服务契约之后,接口的方法成员并不能自动成为服务的操作。在此方面,WCF采用的是显式选择(Explicit Opt-in)的策略:我们须要在相应的操作方法上面显式地应用OperationContractAttribute特性。

 

 

 

posted @ 2010-04-06 21:40 戈多 阅读(48) 评论(0) 编辑

2008年7月30日 #

开发asp.net 程序时最常用的验证模式就是基于窗体的身份验证模式,结合global.asawebconfig可以快速实现此种机制。笼统的说,该过程是先建一个文件夹,然后把要保护的页面放进去,接着设置一下web,config,这样就完成了保护。如果你要访问这个文件夹,就会被强制转到预先设定的登录页面,你填上正确的用户名和密码,提交,系统验证后,就把你的登陆信息写到cookie里面,这样你再去访问那个文件夹,就可以进去了,因为你的登陆凭证已经保存到cookie里面了。
    先要建一个asp.net应用程序,这里面至少要有一个登录用的页面,然后修改你的根目录下的web.config,把验证那一块改成Forms验证模式。
 <authentication mode="Forms">
      
<forms loginUrl="Login.aspx" />
 
</authentication>
 
<authorization>
     
<deny users="?" />
 
</authorization>
     接下来在要保护的文件夹里放一个web.config,要注意的是,这个子文件夹里的web.config的实际内容不能像根目录下的那个一样多,否则就会出现配置错误,提示在应用程序级别以外使用注册为 allowDefinition='MachineToApplication' 的节是错误的。导致该错误的原因可能是在 IIS 中没有将虚拟目录作为应用程序进行配置。具体应该怎么做我也不清楚,总之这个web.config只要有下面的内容就ok了。
   
<configuration>
  
<system.web>
    
<authorization>
     
<!--设置准许访问此文件夹的角色和拒绝的角色,这里准许管理员,老师访问,拒绝学生访问-->
       
<allow roles="admin" />
       
<allow roles="teacher" />
       
<deny roles="student" />
       
<!--前提是拒绝匿名用户!-->
       
<deny users="?" />
    
</authorization>
 
</system.web>
</configuration>
  当然也可以在顶层web.config文件中完成所有的url授权,而不是把它们分在各自目录下的web,config文件中。asp.net也支持这种做法。下面这个web,config文件,放在应用程序根目录下。
 如下:此设置是保护admin文件夹下的内容,拒绝匿名用户访问
 
<location path="admin">
  
<system.web>
   
<authorization>
     
<deny users="?"></deny>
   
</authorization>
   
</system.web>
</location>
   好了,设置完了,下面就开始为我们的窗体验证写代码了
   有两种方式,第一种,当网站的用户不是很多的时候,可以把用户和密码放到web.config里。办法就是在根目录下的web.config文件中加入一个credentials节,里面写上用户名和密码,这个是包含在forms节里面的。
   如下所示:
<authentication mode="Forms" >
   
<forms loginUrl="login.aspx">
     
<credentials passwordFormat="Clear">
      
<user name="admin" password="admin"/>
     
</credentials>
   
</forms>
</authentication>
   在此种情况下  配合使用System.Web.Security.FormsAuthentication.Authenticate(string name,string password)验证credentials节中指定的用户名和密码,存在就返回true。


  下面着重介绍第二种方法,通过数据库读取用户名密码进行验证。
    1:首先在数据库里建立三张表: Users(UserID,UserName,UserPwd)---存放用户信息
                              Roles(RoleID,RoleName)------存放角色名称
                              User_Role(UserID,RoleID)-----用户和角色的中间表,使头两张表成为多对多关系

    2:然后在登陆页面的登陆按钮点击事件中加入如下逻辑
 
if (Page.IsValid) 
       
{
            
if(Users.Authenticate(txtUsername.Text, txtPassword.Text))//数据库验证方法,代码略
            {
                 
//验证后导向初始页
                   FormsAuthentication.RedirectFromLoginPage( txtUsername.Text, chkRemember.Checked ;
               }

        }
    在此也可以用 FormsAuthentication.SetAuthCookie(email.Text, RememberCheckbox.Checked);该方法不进行页面导向,而是停留在本页,然后由自己选择导向的页面。

    3:然后就要用到global.asax文件下的Application_AuthenticateRequest事件了,此事件在每次访问aspx文件都会触发。
在其中加入如下代码,功能见注释:
   
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        
{
            
            
if (Request.IsAuthenticated == true//如果验证了用户,则为 true,否则为 false
            {  
                String[] roles;
                
// 首次登陆,还没有存入角色cookies
                if ((Request.Cookies["userlroles"== null|| (Request.Cookies["userlroles"].Value == ""))    
                
{
                    
// 此时调用方法,访问数据库中的记录获得用户角色,并存入cookies
                    roles =(String[]) Users.GetRoles(User.Identity.Name).ToArray(typeof(String));
                    String roleStr 
= "";
                    
foreach (String role in roles)     //一个用户会有多种角色,以一个字符串表示,用;隔开
                    {
                        roleStr 
+= role;
                        roleStr 
+= ";";
                    }

                    
//创建cookies票据
                    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                        
1,                              //版本
                        Context.User.Identity.Name,     //登陆时候存入的标识用户的用户名
                        DateTime.Now,                   // 发布时间
                        DateTime.Now.AddHours(1),       // 过期时间
                        false,                          // 是否持久
                        roleStr                         // 角色字符串
                        );

                    
// 加密票剧
                    String cookieStr = FormsAuthentication.Encrypt(ticket);
                    
//发送到客户端,起名userroles
                    Response.Cookies["userroles"].Value = cookieStr;//必须加密
                    Response.Cookies["userroles"].Path = "/";
                    Response.Cookies[
"userroles"].Expires = DateTime.Now.AddMinutes(1);
                }

              
else 
              
{
                    
// 已存在,读取,解密
         FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies["userroles"].Value);
                    
//把角色字符添加到list里
                 ArrayList userRoles = new ArrayList();
               
foreach (String role in ticket.UserData.Split( new char[] {';'} )) 
               
{
                    userRoles.Add(role);
                 }

                 roles 
= (String[]) userRoles.ToArray(typeof(String));
                }

                
// 把此用户的角色存到内存中,可以运用User.IsInRole()方法进行检验用户角色
                
// 也可以使用实现IPrincipal接口的类,自定义赋值给Context.User
                Context.User= new GenericPrincipal(Context.User.Identity, roles);
               }

        }
   4:然后添加读取验证用户是否存在的访问数据库代码,和获得用户角色的代码。
      详细码略,这里主要争对三张表写出获得用户角色的存储过程
    
CREATE PROCEDURE User_GetUserRolesByUsername 
(
    @Username  nvarchar(
50)
)
AS
select Roles.RoleName
from Roles
join Users on Users.Username
=@Username
join User_Role on User_Role.UserID
=Users.UserID
where Roles.RoleID
=User_Role.RoleID
GO
 
posted @ 2008-07-30 23:14 戈多 阅读(90) 评论(0) 编辑

2008年7月28日 #

授权的目的是确定是否应该授予某个标识对给定资源请求的访问权限类型。有两种基本方式来授予对给定资源的访问权限:

  • 文件授权

文件授权由 FileAuthorizationModule 执行,它在使用 Windows 身份验证时处于活动状态。它执行 .aspx .asmx 处理程序文件的访问控制列表 (ACL) 检查以确定用户是否应该具有访问权限。应用程序可以进一步使用模拟在正在访问的资源上进行资源检查。

  • URL 授权

URL 授权由 URLAuthorizationModule 执行,它将用户和角色映射到 URL 命名空间的块上。此模块实现正和负两种授权断言。也就是说,对于某些集、用户或角色,该模块可用于有选择地允许或拒绝对 URL 命名空间的任意部分的访问。

URLAuthorizationModule 在任何时候都是可用的。只需在配置文件的 <authorization> 部分的 <allow> <deny> 元素中放置用户和/或角色的列表即可。

若要建立访问特定目录的条件,则必须将一个包含 <authorization> 部分的配置文件放置在该目录中。为该目录设置的条件也会应用到其子目录,除非子目录中的配置文件重写这些条件。此部分的常规语法如下所示。

<[element] [users] [roles] [verbs]/>

元素是必需的。必须包含 users roles 属性。可以同时包含二者,但这不是必需的。verbs 属性是可选的。

允许的元素有 <allow> <deny>,它们分别授予和撤消访问权限。每个元素支持三个属性,这些属性在下面的表中定义。

属性

说明

roles

标识此元素的目标角色。请求所关联的 IPrincipal 对象确定角色成员。可以将任意 IPrincipal 对象附加到给定请求的上下文中,这些对象可通过您喜欢的任何方式来确定角色成员。例如,默认的 WindowsPrincipal 类使用 Microsoft Windows NT 组来确定角色成员。

users

标识此元素的目标身份。

verbs

定义操作所要应用到的 HTTP 谓词,如 GETHEAD POST

还会拒绝匿名用户。

以下示例向 Kim 和管理角色的成员授予权限,而拒绝 John 和所有匿名用户:

<authorization>

    <allow users="Kim"/>

    <allow roles="Admins"/>

    <deny users="John"/>

    <deny users="?"/>

</authorization>

用户和角色都可以通过使用逗号分隔的列表来引用多个实体,如下面的示例所示。

<allow users="John, Kim, contoso\Jane"/>

注意,域帐户 (contoso\Jane) 必须同时包括域和用户名的组合。

除身份名称外,还有两种特殊身份,如下表所示。

标识

说明

*

指所有身份

?

指匿名身份

若要允许 John 并拒绝其他任何人,可以构造下面的配置部分。

<authorization>

    <allow users="John"/>

    <deny users="*"/>

</authorization>

下面的示例允许每个人使用 GET,但只有 Kim 可以使用 POST

<authorization>

    <allow verb="GET" users="*"/>

    <allow verb="POST" users="Kim"/>

    <deny verb="POST" users="*"/>

</authorization>

使用下面的试探法应用规则:

  • 位于较低目录级别的配置文件中包含的规则优先于位于较高目录级别的规则。系统通过构造一个 URL 的所有规则的合并列表,其中最近(层次结构中距离最近)的规则位于列表头,来确定哪条规则优先。
  • 给定 URL 的一组合并的规则,系统从列表头开始,检查规则直到找到第一个匹配项为止。注意,ASP.NET 的默认配置包含向所有用户授权的 <allow users="*"> 元素。如果没有匹配的规则,则将允许请求,除非另外拒绝。如果找到匹配项并且匹配项是 <deny> 元素,则它将返回 401 状态代码。应用程序或站点可以方便地配置位于其站点或应用程序顶层的 <deny users="*"> 元素以防止此行为。

如果是 <allow> 匹配,则模块不执行任何操作,允许进一步处理请求。

还有 <location> 标记,您可以使用该标记来指定特定的文件或目录,由该标记环绕(即在 <location> </location> 标记之间)的那些设置将应用到该文件或目录。

posted @ 2008-07-28 01:52 戈多 阅读(766) 评论(0) 编辑

2008年7月24日 #

posted @ 2008-07-24 01:45 戈多 阅读(60) 评论(0) 编辑

2008年7月13日 #

posted @ 2008-07-13 23:23 戈多 阅读(1084) 评论(0) 编辑

2008年6月26日 #

posted @ 2008-06-26 14:04 戈多 阅读(97) 评论(0) 编辑

2008年6月3日 #

posted @ 2008-06-03 16:19 戈多 阅读(112) 评论(0) 编辑

2008年5月20日 #

posted @ 2008-05-20 17:24 戈多 阅读(292) 评论(0) 编辑