WebService和.net Remoting二者哪一个好一些

请问各位高手:WebService和.net Remoting二者哪一个好一些(谢绝灌水)?

二者各有何优缺点?

哪一个效率高一些?

哪一个安全性好一些?

欢迎各位高手指点!多谢!


 
 
 
lovewindy(LOVE风云) 于 2005-9-2 14:45:09

好坏?都不能一概而论,要看具体的应用.
Remoting主要用在局域网内的集群,因为他在公网上安全性比较差.
而WebService,以一种服务的形式,向其他人提供.
 
 
hzw66(超越理想) 于 2005-9-2 14:46:05

remoting是有状态的,是紧密耦合;web service是无状态的,是松散耦合;
总的来说remoting适合局域网内,对性能和响应效率要求较高的场合;
而web service适合跨网络,跨系统,对移植性和通用性要求较高的场合;
remoting和web service严格的说都不是和J2EE的EJB对应的技术,如果一定要比较,
那么部署在COM+/MTS的.net remoting组件可以和EJB对应。公允的说,目前DotNet
在企业级应用上的结构还不完整。
 
 
athossmth(athos) 于 2005-9-2 15:23:32

hzw66说了
 
 
JamesLee2003 于 2005-9-2 15:29:11

多谢楼上几位。

我做的是在internet上的,不需要跨系统。要求就是一个是效率,一个是安全性。

这么说,应该是.net Remoting的效率比web service高一些,是吗?

如果是这样,它们的安全性呢?

多谢各位,明白了马上给分。
 
 
weisunding(鼎鼎) 于 2005-9-2 15:44:30

MSDN上最新测试文章表明,webservice总体性能优于.net remoting,webservice响应速度更快。

.net remoting 对象序列化和反序列化太花时间。

 

 

首 页网络编程
网页制作图形图象 操作系统冲浪宝典
软件教学认证考试

网络安全 网络办公行业资讯评测对比
您当前位置:站长天空 -> 网络编程-> JSP教程
MSMQ,Enterprise Service, DotNet Remoting,Web Service 的优缺点-.NET教程,Web Service开发
作者:网友供稿 点击:4
推荐
西部数码-全国 虚拟主机10强!20余项 虚拟主机管理功能,全国领先!第6代 双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计, 企业邮局.Cn 域名注册58元/年,空间150元起,免费试用7天,满意再付款!P4 主机租用799元/月.月付免压金
 
站内搜索
文章页数:[1] 
对于送耦合的引用,有一下四种选项。

1.msmq

从windows nt 开始微软就开始提供msmq 的支持,一直到现在的3.0,主要提供一下几个特性的支持。
可靠的消息传递,类似mail 系统,有脱机支持
可设置消息的优先级,label的各种额外的标示
事务支持
通过dc,ic的灵活应用,有好的缩放性

对于客户端,要求必须是windows 系统,从windowsce 到windows .net 2003 都作支持。可以通过连接器跟其他的非微软技术集成.net 有一个专门的封装 system.messaing namespace.

2.enterprise service

.net 中其实通过托管的enterprise service 跟 com+ 应用架构交互。

从windows 2000 开始有这个组件,目前到windows 2003 版本是1.1

我认为有几个特性值得一用
对象池,对于对象构造特别慢,而又没有状态的应用特别适合。很类似我们 ado.net 中的连接吃。可以跟jit去结合。
分布式事务协调,加上事务补偿。这是一大优点
另外一点就是送耦合事件,这一点对于plug and play 的订阅式应用很有帮助。

当然直接的客户端也必须是 windows 2000 以及以上的os

3.dotnet remoting
这个我用的最多,感觉也最深;)

dotnet remoing 的中文翻译时远程处理,其实是一种.net 平台下面很好的一种远程处理调用,提供了开发的架构。灵活的通讯传输协议,当然也可以自己去扩展。远程对象的调用提供了多种方式,可以使有状态的,也可以使无状态。对于开发人员,感觉根本地调用一样方便。这一点主要却别于web service。

其实这种应用类似一个相对耦合的应用。客户端和服务端丰富的通讯模型是基于.net 平台。也就是说如果客户端不一定是.net 平台的话,remoting 就显得不是很适合。一个简单的例子就是对象的传递

从remoting 服务端传递一个对象给客户端,可以是对象的远程的一个远程引用,也可以使一个对象的copy,就是我们通常说的mbr 或者mbv

当然,web 服务是无法实现对象的引用传递,web 服务只能是一个mbv,而web 服务这里的mbv 作的就不够彻底了。我在http://dotnet.mblogger.cn/montaque/posts/2094.aspx 提到他们走的不同的序列化方式。对于web 服务,只是一个很浅的copy。也就是说对象在传递到服务端的时候,并没有把 100% 的状态传递过去。

而remoting 传递的对象就比较地道。或许这就是一个.net remoting 相对于web 服务比较更贴近本地调用的一个体现

缺点前面提到了,就是丰富的特性是基于。net 这个平台。.net 中通过 system.runtime.remoting.dll

4. web 服务。
这是个标准的东西,我的意见是标准的东西不见的都是最好的。在保证标准的同时,丢失了很多特性。

文章页数:[1] 

 


放大字体显示缩小字体显示打印文章推荐给朋友 
热门文章 
·用正则表达式得到网页上的链接-.NET教程,评论及其它
·VB.NET里奇怪的数组赋值现象-.NET教程,VB.Net语言
·学习javabean-JSP教程,Java技巧及代码
·Hibernate 配置!-JSP教程,资料/其它
·jsp页面中的下载功能实现-JSP教程,Jsp/Servlet
·java中的常见问题-JSP教程,Java技巧及代码
·西门子将在京建中国总部 投资额高达10亿元
·java、J2EE基础问题汇总-JSP教程,Java技巧及代码
·利用 Java Web Start发布你用java程序-JSP教程,Java技巧及代码
·JSP生成jpeg图片用于投票-JSP教程,Jsp/Servlet
最新文章 
·ado连接数据库模块-.NET教程,数据库应用
·VB6如何让程序只能启动一个实例-.NET教程,Asp.Net开发
·如何保存一个字符串Cookie,在其它WebForm中可以访问到?-ASP教程,ASP应用
·使用.Net获取OLEDB数据库的架构.-.NET教程,数据库应用
·用正则表达式得到网页上的链接-.NET教程,评论及其它
·MSMQ,Enterprise Service, DotNet Remoting,Web Service 的优缺点-.NET教程,Web Service开发
·java、J2EE基础问题汇总-JSP教程,Java技巧及代码
·利用 Java Web Start发布你用java程序-JSP教程,Java技巧及代码
·我写ASP时常用到的一些函数-ASP教程,ASP应用
·VB.NET里奇怪的数组赋值现象-.NET教程,VB.Net语言
相关主题 
 
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
 发表评论 打印  刷新     关闭
 

网上大名:
 

 

 

请问.NET Remoting 和 Web Service有啥本质的区别?

如题,好像都是远程对象调用和消息交互
 
 
 
pierven(牛牛) 于 2005-1-14 9:52:09

可以实现的功能上区别不是很大,不过remoting是通过在客户端创建代理来访问服务端的对象来实现,而service则是将对象用标准的xml来传输。remoting可以基于多种网络协议,http、tcp。而service是http上的。remoting的性能可能要比service好些
 
 
rustical(时光流逝) 于 2005-1-14 10:02:35

remoting 是有状态的object,不能够跨平台
webservices 是无状态的object, 能够跨平台

 
 
Sunmast(速马, C++/CLI) 于 2005-1-17 12:57:15

http://blog.sunmast.com/Sunmast/archive/2005/01/17/1168.aspx
 
 
haoztao(.NET一族) 于 2005-1-19 15:09:43

http://www.microsoft.com/china/community/chat/chatrecord/chat20021017_2.mspx
 
 
thinkforever 于 2005-1-19 15:12:53

呵呵,回答得都不太对头。看官方文档.
 
 
huangsuipeng(hsp|I love foxpig) 于 2005-1-19 23:54:36

webservices 也可以有状态嘛
 
 
sutalon(神州无敌) 于 2005-1-20 0:26:11

webservices 是基于 soap 协议的,用 xml 来传输,所以了,能跨平台

现在。webservices 用的好像不多了

 

 

.NET Remoting与分布式应用开发——初识 Remoting

作者:叶小舟

下载源代码

一、Remoting简介

  .NET Remoting(下文简称Remoting)是一种可用于开发分布式应用程序的技术。其主要的结构,分为:远程对象、提供远程对象的远程服务器,以及可以访问何使用远程对象的客户端。这三个部分,可以分布于同一台计算机的同一个进程,或者是不同的进程,也可以是处于网络上的不同的计算机。Remoting技术最大的特点,就是对远程通信的过程进行了抽象和封装,使开发人员不必去处理底层通信的细节,而可以把重点放在对业务逻辑的处理上。而且Remoting的通信协议也比较灵活,可以使用多个通信协议、不同的数据格式类型,以及不同类型的序列化机制。在某些情况下,Remoting还允许你使用自定义的数据格式。

二、.NET Remoting与DCOM

  说到这里,你也许会想到DCOM(分布式组件对象模型),在以前的分布式应用中,DCOM是一种比较高效的解决方案。和Remoting技术相比,DCOM在进行数据传输的时候,使用的是专有的二进制数据格式,而Remoting可以使用任意一种格式,包括二进制格式和XML格式,以及用户自定义的数据格式。DCOM的另外一个问题,就是在网络环境中,大部分的防火墙不允许DCOM穿过,解决的办法是重新配置防火墙。利用Remoting,可以轻松的穿过防火墙,一切可以顺利的进行 :)。因此,在实质上,可以认为Remoting是DCOM针对.NET的改进版本。

三、.NET Remoting与Web Service

  运行于Internet的分布式应用程序,Web Service是首选的解决方案,因为Web Service能够穿透足够安全的防火墙,虽然Remoting技术也可以实现这样的功能,但是对于Internet解决方案,Web Service仍是首选。和Web Service相比,Web Service需要Web服务器的支持,Remoting不需要Web服务器,它是使用自己的HTTP或者TCP服务器。在内部网络的解决方案中,Remoting拥有足够的优势,当采用TCP和二进制数据传输的时候,能有更高的效率。不过有一点值得注意:Web Service可以跨平台运行,而Remoting只能运行在.NET FrameWork的平台下。

四、简单的例子,开始我们的Remoting之旅

  讲了这么多,都是理论的东西,相信大家已经跃跃欲试了。下面我们还是按照老规矩,用一个经典的Hello World来开始我们的Remoting之旅吧!我们的例子,也是分三步开始:

  1. 建立远程对象;
  2. 建立远程服务器;
  3. 建立客户端程序,调用远程对象;

准备好了吗?Let''s go~!

首先,我们编写远程对象的类

		
          namespace RemoteObject
          {
	      public __gc class RemoteObjClass:public MarshalByRefObject
	      {
		   public:
			String * DisplayMessage()
			{
			    return S"Hello World!";
			}
	      };
          }      

  这是一个很简单的类,DisplayMessage成员函数,返回一串字符:Hello World。在这里,我们要注意MarshalByRefObject,我们的类就是从它继承而来。在.NET中有应用程序域的概念,MarshalByRefObject类,能让对象跨应用域被访问。

然后,我们来建立远程服务器,代码如下:

           using namespace System;
	   using namespace System::Runtime::Remoting;
	   using namespace System::Runtime::Remoting::Channels;
	   using namespace System::Runtime::Remoting::Channels::Tcp;
           using namespace RemoteObject;

	  int _tmain()
	  {
    	     // TODO: 请用您自己的代码替换下面的示例代码。
	     TcpChannel *Channel=new TcpChannel(8888);
	     ChannelServices::RegisterChannel(Channel);
	     RemotingConfiguration::RegisterWellKnownServiceType(
		Type::GetType(
			"RemoteObject.RemoteObjClass,RemoteObject"),
			 S"Test",WellKnownObjectMode::SingleCall);

   	     Console::WriteLine(S"Server is running...");
	     Console::ReadLine();
	     return 0;
          }      

(注:服务端和客户端,由于用到Remoting相关的类,所以需要在工程中,添加对System.Runtime.Retmoting的引用)
服务器和客户端之间的通信,是借由通道来实现的。在我们的服务器的代码中,首先,就是建立一个端口好为8888的Tcp通道,数据使用二进制方式传输,这样,服务器端将在端口8888进行监听。然后ChannelServices::RegisterChannel注册Tcp通道和服务。RemotingConfiguration::RegisterWellKnownServiceType把需要被远程访问的对象注册为已知类型。第一个参数,为对象的类型,第二个参数,是一个字符串,它和远程客户端访问的时候,用的URI有关。举个例子,在我们的程序中,本机调试的情况下,客户端访问客户端的远程对象的时候URI的地址就为: tcp://localhost:8888/Test ,localhost是指向本机的,如果在内部网络中,可以指定为服务器端的IP地址。 第三个参数,是调用的方式,在Remoting中,分为Singleton和SingleCall。二者的差别,我在以后的文章中会介绍。SingleCall,会在客户端每次访问的时候,创建一个实例,而Singleton只是创建一个实例,以后客户端的调用,都是共享这个实例。

实现远程客户端:

       #include "stdafx.h"
       #using 
 
 

       using namespace System;
       using namespace System::Runtime::Remoting;
       using namespace System::Runtime::Remoting::Channels;
       using namespace System::Runtime::Remoting::Channels::Tcp;

       using namespace RemoteObject;

       int _tmain()
       {
           TcpClientChannel *Channel=new TcpClientChannel();
	   ChannelServices::RegisterChannel(Channel);

           RemoteObjClass *pObj=static_cast
 
 (
				Activator::GetObject(
					Type::GetType("RemoteObject.RemoteObjClass,RemoteObject"),
					S"tcp://localhost:8888/Test"));

	   Console::WriteLine(S"Return String is:{0}",pObj->DisplayMessage());
	   Console::ReadLine();
	   return 0;
       }      

  在我们建立了服务端和远程对象之后,客户端就比较简单了。主要就是创建一个TcpChannel对象,用于和服务器端通信,不同的地方,是我们不需要指定一个端口。因为在客户端可以使用任何一个随机的端口。Activator::GetObject用来获取对远程对象的引用。之后,我们就可以像调用本地对象一样,来调用远程对象的方法了。程序的运行结果如下图:

  整个过程就是这样了。和DCOM相比较,我们会看到,Remoting比DCOM简化了很多。在以后的文章,我会详细介绍Remoting的其他功能和特性。 以上程序,需要.NET Framework 1.1的支持。

 

关于ASP.NET中的上下文

关于上下文
 
作者:Susan Warren | 来自:MSDN | 浏览: <script src="../../../count.asp?id=157" type="text/javascript"></script>166
 
Susan Warren
Microsoft Corporation
2002年1月14日

 

编写 Web 应用程序时最常见的问题之一,是要让代码知道它的执行上下文。让我们通过一个简单的例子(即个性化页面)来说明这个问题:

     请登录。

     欢迎 Susan!

虽然看起来很简单,但即使是这一小段 Web UI,仍然需要好几段信息,而且每次请求该页时这些信息都会发生变化。我们需要知道以下内容:

  1. 用户登录了吗?
  2. 用户的显示名是什么?

更通常的问题是,每次请求该页时,唯一的上下文是什么?以及如何编写代码以便能考虑到此信息?

事实上,由于 HTTP 的无状态特性,Web 应用程序可能需要跟踪许多不同的上下文片段。当用户与 Web 应用程序交互时,浏览器将一系列独立的 HTTP 请求发送到 Web 服务器。应用程序自身必须将这些请求组织成令用户感到愉悦的体验;同时,知道请求的上下文也十分关键。

ASP 引入了几个内部对象,如 RequestApplication,以便帮助跟踪 HTTP 请求的上下文。ASP.NET 完成下一步骤,并将这些对象以及其他几个与上下文有关的对象捆绑在一起,形成一个极为方便的内部对象 Context

Context System.Web.HttpContext(英文)类型的对象。它作为 ASP.NET Page 类的属性公开。也可以通过用户控件和业务对象(下文中详细介绍)获得该对象。以下是 HttpContext 形成的对象的部分列表:

对象说明
Application 值的关键字/值对集合,可由应用程序的每个用户访问。Application 是 System.Web.HttpApplicationState 类型。
ApplicationInstance 实际运行的应用程序,它公开一些请求处理事件。这些事件在 Global.asax、HttpHandler 或 HttpModule 中处理。
Cache ASP.NET Cache 对象,它提供对缓存的编程访问。Rob Howard 的 ASP.NET Caching 专栏(英文)对缓存作了详尽介绍。
Error 处理页时遇到的第一个错误(如果有)。有关详细信息,请参阅 Rob 撰写的 Exception to the Rule, Part 1(英文)。
Items 关键字/值对集合,可以用来在参与处理同一请求的所有组件之间传递信息。Items 是 System.Collections.IDictionary 类型。
Request 有关 HTTP 请求的信息,包括浏览器信息、Cookies 以及在窗体或查询字符串中传递的值。Request 是 System.Web.HttpRequest 类型。
Response 用于创建 HTTP 响应的设置和内容。Response 是 System.Web.HttpResponse 类型。
Server 服务器是一个实用程序类,带有一些有用的帮助器方法,包括 Server.Execute()Server.MapPath()Server.HtmlEncode()。Server 是 System.Web.HttpServerUtility 类型的对象。
Session 值的关键字/值对集合,可由应用程序的单个用户访问。Session 是 System.Web.HttpSessionState 类型。
Trace ASP.NET 的 Trace 对象,提供对跟踪功能的访问。有关详细信息,请参阅 Rob 撰写的文章 Tracing(英文)。
User 当前用户(如果已经过身份验证)的安全上下文。Context.User.Identity 是用户的名称。User 是 System.Security.Principle.IPrincipal 类型的对象。

如果您是一位 ASP 开发人员,那么对上面讲述的部分对象应不会感到陌生。虽然有一些改进,但大体而言,它们在 ASP.NET 中的作用与在 ASP 中是完全一样的。

Context 基础知识

Context 中的部分对象也已升级为 Page 中的顶级对象。例如,Page.Context.ResponsePage.Response 指的是同一个对象,因此,以下代码是等价的:

[Visual Basic® Web 窗体]
   Response.Write ("您好")
   Context.Response.Write ("你好")
[C# Web 窗体]
   Response.Write ("您好");
   Context.Response.Write ("你好");

还可以从业务对象使用 Context 对象。HttpContext.Current 是静态属性,可以很方便地返回当前请求的上下文。这在各种方法中都十分有用,下面仅列举一个从业务类的缓存中检索项目的简单示例:

[Visual Basic]
      ' 获取请求上下文
      Dim _context As HttpContext = HttpContext.Current

   ' 获取缓存中的数据集
   Dim _data As DataSet = _context.Cache("MyDataSet")
[C#]
      // 获取请求上下文
      HttpContext _context = HttpContext.Current;

   // 获取缓存中的数据集
   DataSet _data = _context.Cache("MyDataSet");
操作中的 Context

Context 对象为一些常见的 ASP.NET“如何…?”问题提供了答案。也许,说明此宝贵对象的价值的最好方法,就是在操作中将它展示出来。下面是一些我所知道的最巧妙的 Context 技巧。

我如何从自己的业务类中生成 ASP.NET 跟踪语句?

回答:很简单!使用 HttpContext.Current 获取 Context 对象,然后调用 Context.Trace.Write()

[Visual Basic]
Imports System
Imports System.Web

Namespace Context

   ' 演示从业务类中生成一个 ASP.NET 
   ' 跟踪语句。

   Public Class TraceEmit
      
      Public Sub SomeMethod()
         
         ' 获取请求上下文
         Dim _context As HttpContext = HttpContext.Current
         
         ' 使用上下文编写跟踪语句
         _context.Trace.Write("在 TraceEmit.SomeMethod 中")

      End Sub

   End Class

End Namespace   
[C#]
using System;
using System.Web;

namespace Context
{
   // 演示从业务类中生成一个 ASP.NET 
   // 跟踪语句。

   public class TraceEmit
   {

        public void SomeMethod() {
        
            // 获取请求上下文
            HttpContext _context = HttpContext.Current;

            // 使用上下文编写跟踪语句
            _context.Trace.Write("在 TraceEmit.SomeMethod 中");
        }
    }
}
如何才能从业务类中访问会话状态值?

回答:很简单!使用 HttpContext.Current 获取 Context 对象,然后访问 Context.Session

[Visual Basic]
Imports System
Imports System.Web

Namespace Context

   ' 演示从业务类中访问 ASP.NET 内部
   ' 会话。

   Public Class UseSession
   
      Public Sub SomeMethod()
         
         ' 获取请求上下文
         Dim _context As HttpContext = HttpContext.Current
         
         ' 访问内部会话
         Dim _value As Object = _context.Session("TheValue")

      End Sub

   End Class

End Namespace
[C#]
using System;
using System.Web;

namespace Context
{
   // 演示从业务类中访问 ASP.NET 内部 
   // 会话

   public class UseSession
   {

        public void SomeMethod() {
        
            // 获取请求上下文
            HttpContext _context = HttpContext.Current;

            // 访问内部会话
            object _value = _context.Session["TheValue"];
        }
    }
}
如何才能在应用程序的每页中添加标准页眉和页脚?

回答:处理应用程序的 BeginRequestEndRequest 事件,并使用 Context.Response.Write 生成页眉和页脚的 HTML。

从技术上讲,可以在 HttpModule 中或通过使用 Global.asax 处理 BeginRequest 这样的应用程序。HttpModules 的编写比较困难,而且正如本例所示,简单应用程序使用的功能通常不使用它。因此,我们使用应用程序范围的 Global.asax 文件。

与 ASP 页一样,一些固有的 ASP.NET 上下文已提升为 HttpApplication 类的属性,其中的类表示 Global.asax 继承类。我们不需要使用 HttpContext.Current 获取对 Context 对象的引用;它在 Global.asax. 中已可用。

本例中,我将 <html><body> 标记以及一条水平线放入页眉部分,而将另一条水平线及相应的结束标记放入页脚部分。页脚还包含版权消息。运行结果应如下图所示:

图 1:浏览器中呈现的标准页眉和页脚示例

这是一个简单的示例,但您可以很容易地将它扩展,使其包含标准的页眉与导航,或者仅输出相应的 <!-- #include ---> 语句。请注意,如果希望页眉或页脚包含交互内容,应考虑使用 ASP.NET 用户控件。

[SomePage.aspx 源代码 - 内容示例]
<FONT face="Arial" color="#cc66cc" size="5">
常规页面内容
</FONT>
[Visual Basic Global.asax]
<%@ Application Language="VB" %>

<script runat="server">

      Sub Application_BeginRequest(sender As Object, e As EventArgs)

         ' 生成页眉
         Context.Response.Write("<html>" + ControlChars.Lf + _
"<body bgcolor=#efefef>" + ControlChars.Lf + "<hr>" + _ ControlChars.Lf)

      End Sub 
      
      
      Sub Application_EndRequest(sender As Object, e As EventArgs)

         ' 生成页脚
         Context.Response.Write("<hr>" + ControlChars.Lf + _
      "2002 Microsoft Corporation 版权所有" + _
      ControlChars.Lf + "</body>" + ControlChars.Lf + "</html>")

      End Sub 

</script>
[C# Global.asax]
<%@ Application Language="C#" %>

<script runat="server">

        void Application_BeginRequest(Object sender, EventArgs e) {

            // 生成页眉
            Context.Response.Write("<html>/n<body bgcolor=#efefef>/n<hr>/n");
        }

        void Application_EndRequest(Object sender, EventArgs e) {

            // 生成页脚
            Context.Response.Write("<hr>/2002 Microsoft Corporation 版权所有/n");
            Context.Response.Write("</body>/n</html>");
        }

</script>
如何在用户经过身份验证后显示欢迎信息?

回答:测试 User 上下文对象以查看用户是否经过身份验证。如果是,还要从 User 对象获取用户名。当然,这是本文开头的示例。

[Visual Basic]
<script language="VB" runat="server">

    Sub Page_Load(sender As Object, e As EventArgs) {

        If User.Identity.IsAuthenticated Then
            welcome.Text = "欢迎" + User.Identity.Name
        Else
            ' 尚未登录,添加一个指向登录页的链接
            welcome.Text = "请登录!"
            welcome.NavigateUrl = "signin.aspx"
        End If

    End Sub

</script>

<asp:HyperLink id="welcome" runat="server" maintainstate="false">
</asp:HyperLink>
[C#]
<script language="C#" runat="server">

    void Page_Load(object sender, EventArgs e) {

        if (User.Identity.IsAuthenticated) {
            welcome.Text = "欢迎" + User.Identity.Name;
        }
        else {
            // 尚未登录,添加一个指向登录页的链接
            welcome.Text = "请登录!";
            welcome.NavigateUrl = "signin.aspx";
        }
    }

</script>

<asp:HyperLink id="welcome" runat="server" maintainstate="false">
</asp:HyperLink>
Context.Items 简介

希望以上示例可以说明,使用手头仅有的上下文信息编写 Web 应用程序是多么容易。那么,如果可以用同样的方法访问您应用程序独有的一些上下文,不是很好吗?

这就是 Context.Items 集合的用途。它使用在参与处理请求的各部分代码中都可用的方法,保存应用程序的请求特有值。例如,同样一条信息可以用在 Global.asax、ASPX 页、页内的用户控件中,也可以由页调用的业务逻辑使用。

请考虑 IBuySpy Portal(英文)应用程序示例。它使用一个简单的主页 DesktopDefault.aspx 来显示门户内容。显示的内容取决于所选择的选项卡,以及用户(如果已经过身份验证)角色。

图 2:IbuySpy 主页

查询字符串包含正被请求的选项卡的 TabIndedx 和 TabId 参数。在处理请求的整个过程中,一直使用此信息筛选要显示给用户的数据。http://www.ibuyspyportal.com/DesktopDefault.aspx?tabindex=1&tabid=2(英文)

要使用查询字符串值,需要首先确保它是一个有效值,如果不是,则要进行一些错误处理。它并不是一大串代码,但是您真的要在每个使用该值的页和组件中复制它吗?当然不!在 Portal 示例中,甚至更多的地方都涉及到它,因为一旦我们知道了 TabId,就可以预先加载其他信息。

Portal 使用查询字符串值作为参数,以构造一个新的 PortalSettings 对象,并将它添加到 Global.asax 的 BeginRequest 事件的 Context.Items 中。由于在每个请求开始处都执行了开始请求,这使得与该选项卡有关的值在应用程序的所有页和组件中都可用。请求完成后,对象将被自动丢弃 - 非常整齐!

[Visual Basic Global.asax]
      Sub Application_BeginRequest(sender As [Object], e As EventArgs)
         
         Dim tabIndex As Integer = 0
         Dim tabId As Integer = 0
         
         ' 从查询字符串获取 TabIndex
         If Not (Request.Params("tabindex") Is Nothing) Then
            tabIndex = Int32.Parse(Request.Params("tabindex"))
         End If
         
         ' 从查询字符串获取 TabID
         If Not (Request.Params("tabid") Is Nothing) Then
            tabId = Int32.Parse(Request.Params("tabid"))
         End If
         
         Context.Items.Add("PortalSettings", _
New PortalSettings(tabIndex, tabId))

      End Sub
[C# Global.asax]
void Application_BeginRequest(Object sender, EventArgs e) {
        
    int tabIndex = 0;
    int tabId = 0;

    // 从查询字符串获取 TabIndex

    if (Request.Params["tabindex"] != null) {               
        tabIndex = Int32.Parse(Request.Params["tabindex"]);
    }
                
    // 从查询字符串获取 TabID

    if (Request.Params["tabid"] != null) {              
        tabId = Int32.Parse(Request.Params["tabid"]);
    }

    Context.Items.Add("PortalSettings", 
new PortalSettings(tabIndex, tabId));
}

DesktopPortalBanner.ascx 用户控件从 Context 请求 PortalSetting 的对象,以访问 Portal 的名称和安全设置。事实上,此模块是操作中的 Context 的一个典型综合示例。为阐明这一点,我已将代码进行了一些简化,并用粗体标记了 HTTP 或应用程序特定的 Context 被访问过的所有地方。

[C# DesktopPortalBanner.ascx]
<%@ Import Namespace="ASPNetPortal" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script language="C#" runat="server">

    public int          tabIndex;
    public bool         ShowTabs = true;
    protected String    LogoffLink = "";

    void Page_Load(Object sender, EventArgs e) {

        // 从当前上下文获取 PortalSettings
  PortalSettings portalSettings = 
(PortalSettings) Context.Items["PortalSettings"];

        // 动态填充门户站点名称
        siteName.Text = portalSettings.PortalName;

        // 如果用户已登录,自定义欢迎信息
        if (Request.IsAuthenticated == true) {
        
            WelcomeMessage.Text = "欢迎" + 
Context.User.Identity.Name + "!<" + 
"span class=Accent" + ">|<" + "/span" + ">";

            // 如果身份验证模式为 Cookie,则提供一个注销链接
            if (Context.User.Identity.AuthenticationType == "Forms") {
                LogoffLink = "<" + "span class=/"Accent/">|</span>/n" + 
"<a href=" + Request.ApplicationPath + 
"/Admin/Logoff.aspx class=SiteLink> 注销" + 
"</a>";
            }
        }

        // 动态显示门户选项卡条
        if (ShowTabs == true) {

            tabIndex = portalSettings.ActiveTab.TabIndex;

            // 生成要向用户显示的选项卡列表                                   
            ArrayList authorizedTabs = new ArrayList();
            int addedTabs = 0;

            for (int i=0; i < portalSettings.DesktopTabs.Count; i++) {
            
                TabStripDetails tab = 
(TabStripDetails)portalSettings.DesktopTabs[i];

                if (PortalSecurity.IsInRoles(tab.AuthorizedRoles)) { 
                    authorizedTabs.Add(tab);
                }

                if (addedTabs == tabIndex) {
                    tabs.SelectedIndex = addedTabs;
                }

                addedTabs++;
            }          

            // 用已授权的选项卡填充页顶部的选项卡
// 列表
            tabs.DataSource = authorizedTabs;
            tabs.DataBind();
        }
    }

</script>
<table width="100%" cellspacing="0" class="HeadBg" border="0">
    <tr valign="top">
        <td colspan="3" align="right">
            <asp:label id="WelcomeMessage" runat="server" />
            <a href="<%= Request.ApplicationPath %>">Portal 主页</a>
<span class="Accent"> |</span> 
<a href="<%= Request.ApplicationPath %>/Docs/Docs.htm">
                Portal 文档</a>
            <%= LogoffLink %>
            &nbsp;&nbsp;
        </td>
    </tr>
    <tr>
        <td width="10" rowspan="2">
            &nbsp;
        </td>
        <td height="40">
            <asp:label id="siteName" runat="server" />
        </td>
        <td align="center" rowspan="2">
      &nbsp;
        </td>
    </tr>
    <tr>
        <td>
            <asp:datalist id="tabs" runat="server">
               <ItemTemplate>
                  &nbsp;
<a href='<%= Request.ApplicationPath %>
/DesktopDefault.aspx?tabindex=<%# Container.ItemIndex %>&tabid=
<%# ((TabStripDetails) Container.DataItem).TabId %>'>
<%# ((TabStripDetails) Container.DataItem).TabName %>
</a>&nbsp;
                </ItemTemplate>
                <SelectedItemTemplate>
                  &nbsp;
                  <span class="SelectedTab">
<%# ((TabStripDetails) Container.DataItem).TabName %>
</span>&nbsp;
                </SelectedItemTemplate>
            </asp:datalist>
        </td>
    </tr>
</table>

您可以使用 Visual Basic 和 C# 在 http://www.ibuyspy.com(英文)联机浏览并运行 IBuySpy Portal 的完整源文件,或者下载后再运行。

小结

Context 是 ASP.NET 中的又一个“精益求精”的功能。它扩展了 ASP 的已经很不错的上下文支持,以便将两个挂钩添加到 ASP.NET 的新运行时功能中。同时添加了 Context.Items,作为短期值的新状态机制。但对于开发人员,此功能的最大好处是使代码更紧凑,且易于维护,而且此上下文我们都能看懂

posted on 2004-11-09 19:02 海天一鸥 阅读(1703) 评论(0)  编辑 收藏 引用 网摘 所属分类: .NET FAQ.NET Web Service /ASP.NET/Remoting

 

WebService 成员

WebService 概述

公共构造函数
公共构造函数WebService 构造函数初始化 WebService 类的新实例。
公共属性
公共属性Application获取当前 HTTP 请求的应用程序对象。
公共属性Container(从 MarshalByValueComponent 继承)获取组件的容器。
公共属性Context获取当前请求的 ASP.NET HttpContext,它封装了由 HTTP 服务器用来处理 Web 请求的所有 HTTP 特定的上下文。
公共属性DesignMode(从 MarshalByValueComponent 继承)获取指示组件当前是否处于设计模式的值。
公共属性Server获取当前请求的 HttpServerUtility
公共属性Session获取当前请求的 HttpSessionState 实例。
公共属性Site(从 MarshalByValueComponent 继承)获取或设置组件的位置。
公共属性User获取 ASP.NET 服务器 User 对象。可用于验证用户是否有权执行请求。
公共方法
公共方法Dispose(从 MarshalByValueComponent 继承)已重载。释放由 MarshalByValueComponent 使用的资源。
公共方法Equals(从 Object 继承)已重载。确定两个 Object 实例是否相等。
公共方法GetHashCode(从 Object 继承)用作特定类型的哈希函数,适合在哈希算法和数据结构(如哈希表)中使用。
公共方法GetService(从 MarshalByValueComponent 继承)获取 IServiceProvider 的实施者。
公共方法GetType(从 Object 继承)获取当前实例的 Type
公共方法ToString(从 Object 继承)返回表示当前 ObjectString
公共事件
公共事件Disposed(从 MarshalByValueComponent 继承)添加事件处理程序以侦听组件上的 Disposed 事件。
受保护的属性
受保护的属性Events(从 MarshalByValueComponent 继承)获取附加到该组件的事件处理程序的列表。
受保护的方法
受保护的方法Dispose(从 MarshalByValueComponent 继承)已重载。释放由 MarshalByValueComponent 使用的资源。
受保护的方法Finalize(从 Object 继承)已重写。允许 Object 在“垃圾回收”回收 Object 之前尝试释放资源并执行其他清理操作。

在 C# 和 C++ 中,使用析构函数语法来表示终结程序。

受保护的方法MemberwiseClone(从 Object 继承)创建当前 Object 的浅表副本。

 

 

 

Running Scripts Remotely

WSH 5.6 can run scripts that reside on remote systems. The following scripts demonstrate this capability. These scripts make the assumption that the files are located on a local machine directory called "c:/wsh5.6"; change the local path and the remote machine name as necessary.

After initially running RemoteTest.WSF on the local machine, there may be a small pause as DCOM verifies your identity. After you see the "Done" message, a file named "c:/beenhere.txt" on the remote machine indicates the time that you executed the command (from the remote computer's clock).

// JScript.
RemoteTest.WSF
------------------------------- 
<package>
<job>
<script language="JScript">
var oController = new ActiveXObject("WSHController");
var oProcess = oController.CreateScript("c://wsh5.6//beenhere.wsf", "remmachine");
oProcess.Execute();
while (oProcess.Status != 2) WScript.Sleep(100);
WScript.Echo("Done"); 
</script>
</job>
</package>
------------------------------- 
BeenHere.WSF
------------------------------- 
<package>
<job>
<script language="JScript">
var fso = new ActiveXObject("Scripting.FileSystemObject");
var fout = fso.CreateTextFile("c://beenhere.txt", true);
fout.WriteLine(new Date);
fout.Close();
</script>
</job>
</package>
------------------------------- 

' VBScript.
RemoteTest.WSF
------------------------------- 
<package>
<job>
<script language="VBScript">
set oController = CreateObject("WSHController")
set oProcess = oController.CreateScript("c:/wsh5.6/beenhere.wsf", "remmachine")
oProcess.Execute
While oProcess.Status <> 2
   WScript.Sleep 100
WEnd
WScript.Echo "Done"
</script>
</job>
</package>
------------------------------- 

BeenHere.WSF
------------------------------- 
<package>
<job>
<script language="VBScript">
set fso = CreateObject("Scripting.FileSystemObject")
set fout = fso.CreateTextFile("c:/beenhere.txt", true)
fout.WriteLine Now
fout.Close
</script>
</job>
</package>
See Also

Basic Windows Script Host Tasks | Setting up Remote WSH | WshRemote Object

 

 

第 11 章 – .NET Remoting 安全性

更新日期: 2004年04月20日
本页内容

本章内容本章内容
目标目标
适用范围适用范围
如何使用本章内容如何使用本章内容
.NET Remoting 体系结构.NET Remoting 体系结构
.NET Remoting 网关守卫.NET Remoting 网关守卫
身份验证身份验证
授权授权
身份验证和授权策略身份验证和授权策略
访问系统资源访问系统资源
访问网络资源访问网络资源
将身份验证的凭据传递给远程对象将身份验证的凭据传递给远程对象
传递原调用方传递原调用方
受信任的子系统受信任的子系统
安全通信安全通信
选择主机进程选择主机进程
远程处理与 Web 服务的比较远程处理与 Web 服务的比较
总结总结

本章内容

.NET Framework 提供了远程处理的基础结构,这样,客户端就可以与驻留在远程应用程序域或进程中的对象或远程计算机上的对象通信。在分布式 Web 应用程序中,.NET Remoting 通常用作一种机制,供表示层组件访问位于中间层的业务逻辑组件。

本章说明如何在使用 .NET Remoting 的分布式 Web 应用程序中实现身份验证、授权和安全通信。

目标

本章的目标是:

实施安全的 .NET Remoting 解决方案。

生成安全的远程组件。

了解使用 .NET Remoting 的分布式应用程序的体系结构和操作,并熟悉 .NET Remoting 的可扩展性功能。

选择适当的主机进程。

标识并使用 .NET Remoting 提供的网关守卫。

将带有调用的客户端凭据传递给远程对象。

将原调用方的标识从远程组件传递给下游系统。

了解何时使用 .NET Remoting 以及何时使用 Web 服务作为您的分布式 Web 应用程序的一部分。

为您的 .NET Remoting 解决方案设计正确的身份验证、授权和安全通信机制。

适用范围

本章适用于以下产品和技术:

Windows XP 或 Windows 2000 Server (Service Pack 3) 和更高版本的操作系统

Microsoft Internet 信息服务 (IIS) 5.0 和更高版本

Microsoft Active Directory

.NET Framework 版本 1.0 (Service Pack 2) 和更高版本

Visual C# .NET

SQL Server 2000 (Service Pack 2) 和更高版本

如何使用本章内容

若要学好本章内容:

您必须具有使用 Visual C# .NET 进行编程的经验。

您必须具有开发和配置 ASP.NET Web 应用程序的经验。

您必须具有配置 SQL Server 安全性、IIS 安全性、Windows 安全性和 Active Directory 的经验。

阅读第 1 章简介。这一章说明了身份验证、授权和安全通信对于分布式 Web 应用程序的重要性。

阅读第 2 章 ASP.NET 应用程序的安全模型。这一章概述了创建分布式 ASP.NET Web 应用程序所采用的体系结构和技术,并重点说明了身份验证、授权和安全通信在该体系结构中适用的位置。

阅读第 3 章身份验证和授权。这一章详细介绍了使用 .NET Remoting 时可用的身份验证机制和授权机制。

阅读第 4 章安全通信。这一章介绍了 SSL 和 IPSec,您将经常使用它们来保护客户端和远程对象之间的通信信道的安全。

阅读第 8 章 ASP.NET 安全性。这一章深入讨论了与 ASP.NET 相关的安全性问题,您在 ASP.NET 中承载远程对象(建议的方式)时会遇到许多此类问题。

请阅读以下章节,其中介绍了如何实现本章所述的许多技术:

如何创建自定义帐户来运行 ASP.NET

如何在 Windows 服务中承载远程对象

如何为 Windows 2000 实现 Kerberos 委派

如何在 Web 服务器上设置 SSL

如何使用 IPSec 在两个服务器之间进行安全通信

如何使用 SSL 来确保与 SQL Server 2000 安全通信

.NET Remoting 体系结构

图 11.1 显示了在 ASP.NET 中驻留远程对象时的基本 .NET Remoting 体系结构。如果主要关心安全性问题,那么建议使用 ASP.NET 主机和 HTTP 通道进行通信,因为它允许远程对象利用 ASP.NET 和 IIS 提供的基本安全服务。

有关可能使用的主机和通道类型范围的详细信息以及比较信息,请参见本章后面的选择主机进程

 .NET Remoting 体系结构

图 11.1
.NET Remoting 体系结构

客户端与进程内的代理对象进行通信。可以通过远程对象代理设置身份验证凭据(例如,用户名、密码和证书等等)。方法调用通过接收链进行传递(您可以实现自己的自定义接收来执行数据加密),并到达负责通过网络发送数据的传输接收。在服务器端,调用通过相同的管道进行传递,并向对象发出调用。

注意:本章中使用的术语代理一词是指客户端进程内的代理对象,客户端通过该对象与远程对象进行通信。不要将它与术语代理服务器混淆。

.NET Remoting 接收

当客户端在远程对象上进行方法调用时,.NET Remoting 使用传输通道接收、自定义通道接收和格式化程序通道接收。

传输通道接收

传输通道接收通过网络在客户端与服务器之间传递方法调用。.NET 提供了 HttpChannel TcpChannel 类,但是,可以对体系结构进行完全扩展,并且插入您自己的自定义实现方法。

HttpChannel。在将远程对象驻留在 ASP.NET 中时,可以使用此通道。此通道使用 HTTP 协议在客户端和服务器之间发送消息。

TcpChannel。在将远程对象驻留在 Microsoft® Windows® 操作系统服务或其他可执行文件中时,可以使用此通道。此通道使用 TCP 套接字在客户端和服务器之间发送消息。

自定义通道。自定义的传输通道可以使用任何基本的传输协议在客户端和服务器之间发送消息。例如,自定义通道可以使用命名管道或邮件槽。

比较传输通道接收

下表对两个主要的传输通道接收进行了比较。

表 11.1: TcpChannel 和 HttpChannel 的比较

功能TCP 通道HTTP 通道注释

身份验证

HTTP 通道使用
IIS 和 ASP.NET 提供的身份验证功能,但是
不支持 Passport 和窗体身份验证。

授权

HTTP 通道支持
IIS 和 ASP.NET 提供的授权功能。
这些授权包括 NTFS 权限、
URL 授权和文件
授权。

安全通信

在 TCP 通道中使用 IPSec。
在 HTTP 通道中使用 SSL
和/或 IPSec。

自定义接收

可以在通道接收管道内的不同位置上使用自定义通道接收来修改在客户端和服务器之间发送的消息。提供加密和解密功能的通道接收就是一个自定义通道接收的示例。

格式化程序接收

格式化程序接收获取方法调用,并将它们序列化为可通过网络发送的流。.NET 提供两种格式化程序接收:

二进制格式化程序。它使用 BinaryFormatter 类将方法调用打包为一个序列化的二进制流,然后传递该流(使用 HTTP POST)以便向服务器发送数据。二进制格式化程序将 HTTP 请求中的内容类型设置为“application/octet-stream”。
与 SOAP 格式化程序相比,二进制格式化程序可以提供更高的性能。

SOAP 格式化程序。它使用 SoapFormatter 类将方法调用打包为 SOAP 消息。在 HTTP 请求中将内容类型设置为“text/xml”,并使用 HTTP POST 将其传递到服务器。

对驻留在 ASP.NET 中的请求进行剖析

远程对象终结点的地址是由以 .rem 或 .soap 扩展文件名结尾的 URL 指定的(例如 http://someserver/vDir/remoteobject.soap)。当 IIS 收到远程对象(带有 .rem 或 .soap 扩展名)的请求时,就会将它映射到 ASP.NET ISAPI 扩展 (Aspnet_isapi.dll) 中。ISAPI 扩展将该请求转发到 ASP.NET 辅助进程 (Aspnet_wp.exe) 中的应用程序域。图 11.2 显示了事件的顺序。

 服务器端处理

图 11.2
服务器端处理

图 11.2 显示了以下事件顺序:

1.

通过 HTTP 接收 .soap 或 .rem 请求,并将其映射到 Web 服务器上的特定虚拟目录。

2.

IIS 检查 .soap/.rem 映射,然后将文件扩展名映射到 ASP.NET ISAPI 扩展 Aspnet_isapi.dll 中。

3.

ISAPI 扩展将请求传递给 ASP.NET 辅助进程 (Aspnet_wp.exe) 中的应用程序域。如果这是在该应用程序上发送的第一个请求,则创建一个新的应用程序域。

4.

调用 HttpRemotingHandlerFactory 处理程序,然后远程处理基础结构读取 Web.config 文件中的 <system.runtime.remoting> 部分,它控制服务器端的对象配置(例如,单个调用或单个参数)和授权参数(使用 <authorization> 元素)。

5.

.NET Remoting 基础结构查找包含远程对象的程序集并对其进行实例化。

6.

.NET Remoting 基础结构读取 HTTP 标头和数据流,然后在远程对象上调用该方法。

注意:在此进程中,ASP.NET 调用正常的事件处理程序序列。您可以有选择地在 Global.asax 中实现一个或多个事件处理程序,例如 BeginRequestAuthenticationRequestAuthorizeRequest 等等。在请求到达远程对象方法时,将代表已验证身份的用户的 IPrincipal 对象存储在 HttpContext.User (和 Thread.CurrentPrincipal)中,并且可以将它用于授权。例如,使用主体权限要求和编程角色检查。

ASP.NET 和 HTTP 通道

.NET Remoting 没有自己的安全模型。客户端(代理)和服务器(远程对象)之间的身份验证和授权是通过通道和主机进程执行的。可以组合使用以下主机和通道:

自定义的可执行文件和 TCP 通道。这种组合不提供任何内置的安全功能。

ASP.NET 和 HTTP 通道。这种组合通过基本的 ASP.NET 和 IIS 安全功能提供身份验证和授权。

ASP.NET 中驻留的对象可以利用 ASP.NET 和 IIS 的基本安全功能。它们包括:

身份验证功能。在 Web.config 中配置 Windows 身份验证功能:

 <authentication mode="Windows"/>
 

IIS 中的设置控制着所使用的 HTTP 身份验证类型。

通用的 HTTP 标头用于对请求进行身份验证。可通过配置远程对象代理为客户端提供凭据,也可以使用默认凭据。

不能使用窗体或 Passport 身份验证,因为通道没有提供允许客户端访问 Cookie 的方法,而这是这两种身份验证机制的一个要求。另外,窗体和 Passport 身份验证需要重定向到要求客户端交互的登录页面。远程的服务器端对象可用于非交互式的场合。

授权功能。使用标准的 ASP.NET 授权方法对客户端进行授权。

可配置的授权选项包括:

URL 授权。

文件授权(它需要特定的配置。有关说明,请参见本章后面的“使用文件授权”)。

编程授权选项包括:

主体权限要求(声明方式和强制方式)。

使用 IPrincipal.IsInRole 进行明确的角色检查。

安全通信功能。应该使用 SSL(和/或 IPSec)保护客户端和服务器之间数据传输的安全。

更多信息

有关 ASP.NET 和 IIS 提供的身份验证和授权功能的详细信息,请参见第 8 章 ASP.NET 安全性。

有关如何在 ASP.NET/IIS 中驻留对象的详细信息,请参见 Microsoft 知识库文章 Q312107 HOW TO: Host a Remote Object in Microsoft Internet Information Services(如何在 Microsoft Internet 信息服务中驻留远程对象)。

.NET Remoting 网关守卫

ASP.NET 承载的远程对象使用的授权点(或者网关守卫)包括:

IIS。如果关闭了匿名身份验证,则 IIS 只接收来自特定用户的请求,即它可以在自己的域或受信任的域中验证这些用户的身份。IIS 还提供 IP 地址和 DNS 筛选功能。

ASP.NET

UrlAuthorizationModule。可以配置应用程序的 Web.config 中的 <authorization> 元素,控制哪些用户和用户组可以访问应用程序。授权是以存储在 HttpContext.User 中的 IPrincipal 对象为基础的。

FileAuthorizationModuleFileAuthorizationModule 可用于远程组件,但这需要进行特定的配置。有关说明,请参见本章后面的使用文件授权

注意:要进行文件授权,并不要求模拟。

FileAuthorizationModule 类只对请求的文件或 URI(例如,.rem 和 .soap)执行访问检查,而不对在远程对象中通过代码访问的文件执行访问检查。

主体权限要求和明确的角色检查。除了使用 IIS 和 ASP.NET 可配置的网关守卫外,还可以将主体权限要求(以声明方式或强制方式)用作附加的细分访问控制机制。通过使用主体权限检查,您可以根据各个用户的标识和组成员身份(由附加到当前线程的 IPrincipal 对象定义)控制对类、方法或个别代码块的访问。

注意:用于请求角色成员身份的主体权限要求与调用 IPrincipal.IsInRole 来测试角色成员身份不同。如果调用方不是指定角色的成员,则前者产生异常,而后者仅返回一个布尔值以确认角色成员身份。

在 Windows 身份验证中,ASP.NET 自动将一个代表已进行身份验证的用户的 WindowsPrincipal 对象附加到当前的 Web 请求(使用 HttpContext.User)。

身份验证

在结合使用远程处理和 ASP.NET Web 应用程序客户端时,就会在 Web 应用程序和远程对象主机上进行身份验证。远程对象主机可以使用的身份验证选项取决于主机类型。

驻留在 ASP.NET 中

当对象驻留在 ASP.NET 中时,可以使用 HTTP 通道在客户端代理和服务器之间传递方法调用。HTTP 通道使用 HTTP 协议对服务器的远程对象代理进行身份验证。

以下列表说明在 ASP.NET 中驻留对象时可以使用的一组身份验证选项:

IIS 身份验证选项:匿名、基本、摘要式、Windows 集成和证书。

ASP.NET 身份验证选项:Windows 身份验证或无(用于自定义的身份验证实现)。

注意:.NET Remoting 不能直接使用窗体和 Passport 身份验证。远程对象调用用于非交互式场合。如果远程对象的客户端是 .NET Web 应用程序,则 Web 应用程序可以使用窗体身份验证和 Passport 身份验证,并将凭据明确地传递给远程对象。在本章后面的传递原调用方一节中将对这种类型的方案进一步进行讨论。

驻留在 Windows 服务中

当对象驻留在 Windows 服务中时,可以使用 TCP 通道在客户端和服务器之间传递方法调用。它使用基于套接字的原始通信方法。因为套接字没有提供身份验证,所以服务器无法对客户端进行身份验证。

在此方案中,远程对象必须使用自定义身份验证。

自定义身份验证

对于简单的自定义身份验证,远程对象可以公开一个接受用户名和密码的 Login 方法。可以根据存储、检索的角色列表以及发回到客户端的令牌对凭据进行验证,以便在后续请求中使用。在服务器上检索到令牌后,可以使用它来创建一个存储在 Thread.CurrentPrincipal 中的 IPrincipal 对象(包含角色)以便进行授权。

其他自定义身份验证的示例还包括:创建使用提供身份验证的进程间通信通道的自定义传输通道接收(例如,命名管道),或者创建使用 Windows 安全服务提供程序接口 (SSPI) 执行身份验证的通道接收。

更多信息

有关如何在 Windows 服务中承载对象的信息,请参见本指南中的如何在 Windows 服务中承载远程对象。

有关接收和接收链的详细信息,请搜索 MSDN 库 .NET Framework 部分中的 Sinks and Sink Chains(接收和接收链)。

有关如何创建使用 SSPI 的自定义身份验证解决方案的详细信息,请参见以下 MSDN 文章“.NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly”(.NET Remoting 安全解决方案第一部分:Microsoft.Samples.Security.SSPI 程序集):http://msdn.microsoft.com/library/en-us/dndotnet/html/remsspi.asp

注意:该文中所述的实现过程是一个示例,而不是经过 Microsoft 测试并得到支持的产品。

授权

当在 ASP.NET 中驻留对象并且使用 HTTP 通道进行通信时,可以对客户端进行身份验证,并使用以下机制来控制授权:

URL 授权

文件授权

主体权限要求(声明方式和强制方式)

代码中的 IPrincipal.IsInRole 检查

当在 Windows 服务中驻留对象时,TCP 通道不提供任何身份验证。因此,您必须通过创建 IPrincipal 对象并将其存储在 Thread.CurrentPrincipal 中,来执行自定义身份验证并进行授权。

然后,可以使用声明方式的主体权限要求检查对远程对象的方法进行注释(如下所示):

[PrincipalPermission(SecurityAction.Demand, 
                     Role="Manager")]
void SomeMethod()
{
}

在对象的方法代码中,也可以使用强制方式的用户权限要求,并可利用 IPrincipal.IsInRole 进行明确的角色检查。

使用文件授权

您可能需要使用内置的 Windows 访问控制将远程对象作为可保护的 Windows 资源保护起来。如果没有文件授权(使用 Windows ACL),则您只能使用 URL 授权。

若要使用 FileAuthorizationModule 授权访问远程对象终结点(用 .rem 或 .soap URL 标识),您必须在应用程序的虚拟目录中创建带有 .rem 或 .soap 扩展名的物理文件。

注意:IIS 使用 .rem 和 .soap 扩展名将对象终结点的请求映射到 ASP.NET ISAPI 扩展 (aspnet_isapi.dll)。通常,它们并不是作为物理文件存在。

为 .NET Remoting 配置文件授权:

1.

在应用程序虚拟目录的根目录中,创建与 objectUri 具有相同名称的文件(例如,RemoteMath.rem)。

2.

在该文件的顶部添加以下行,然后保存该文件:

<%@ webservice class="YourNamespace.YourClass" ... %>

3.

使用 Windows 资源管理器将适当配置的 ACL 添加到该文件中。

注意:可以从用于在服务器上配置远程对象的 web.config 文件中获取 objectUri。查找 <wellknown> 元素,如下例所示:

<wellknown mode="SingleCall" objectUri="RemoteMath.rem" 
type="RemotingObjects.RemoteMath, RemotingObjects, Version=1.0.000.000 
Culture=neutral, PublicKeyToken=4b5ae668c251b606"/>

更多信息

有关这些授权机制的详细信息,请参见第 8 章 ASP.NET 安全性。

身份验证和授权策略

在许多使用 .NET Remoting 的应用程序中,可以使用远程对象在应用程序中间层中提供业务功能,并且 ASP.NET Web 应用程序可以调用该功能。图 11.3 中显示了这种设置。

ASP.NET Web 应用程序调用的远程对象

图 11.3
ASP.NET Web 应用程序调用的远程对象

在此方案中,使用为 Web 应用程序提供的 IIS 和 ASP.NET 网关守卫来保护对客户端代理的访问;而使用为远程应用程序服务器上 ASP.NET 主机提供的 IIS 和 ASP.NET 网关守卫来保护对远程对象的访问。

.NET Web 应用程序访问的远程对象可以使用两种基本的身份验证和授权策略。

可以在 Web 服务器上对调用方进行身份验证和授权,然后使用模拟将调用方的安全性上下文传递给远程对象。这就是模拟/委派模型。
通过使用这种方法,您可以使用允许委派调用方安全性上下文的 IIS 身份验证机制,例如 Kerberos、基本或窗体身份验证(后两个身份验证允许 Web 应用程序访问调用方的凭据),并通过远程对象代理明确地将凭据传递给远程对象。

可以使用 ASP.NET 可配置和编程的网关守卫(包括 URL 授权、文件授权、主体权限要求以及 .NET 角色)在远程对象上对各个调用方进行授权。

您可以在 Web 服务器对调用方进行身份验证和授权,然后使用受信任的标识与远程对象进行通信。这就是受信任的子系统模型。
对于这个模型而言,在调用远程对象之前,要求 Web 应用程序对调用方进行身份验证并进行正确授权。可以对远程对象从 Web 应用程序映射的受信任标识收到的任何请求进行处理。

更多信息

有关模拟/委派模型和受信任的子系统模型的详细信息,请参见第 3 章身份验证和授权中授权方法一节的“资源访问模型”主题。

有关在远程处理过程中使用原调用方模型的详细信息,请参见本章后面的传递原调用方

有关在远程处理过程中使用受信任的子系统模型的详细信息,请参见本章后面的受信任的子系统

访问系统资源

有关从 ASP.NET 中驻留的远程对象访问系统资源(例如,事件日志和注册表)的详细信息,请参见第 8 章 ASP.NET 安全性中的访问系统资源。第 8 章中介绍的方法和限制也适用于 ASP.NET 中驻留的远程对象。

访问网络资源

在从远程对象访问网络资源时,您需要考虑用于响应来自远程计算机的网络身份验证质询的标识。您有三个选项:

进程标识(这是默认标识)。如果在 ASP.NET 中驻留对象,则用于运行 ASP.NET 辅助进程并由 Machine.config 中 <processModel> 元素定义的标识决定了用于资源访问的安全性上下文。
如果在 Windows 服务中驻留对象,则用于运行服务进程的标识(用组件服务 MMC 管理单元配置)决定了用于资源访问的安全性上下文。

固定服务标识。例如,通过调用 LogonUser 创建的标识。

注意:不要将此服务标识与用来运行 Windows 服务的标识混淆起来。固定服务标识是指专为从应用程序访问资源而创建的 Windows 用户帐户。

原调用方标识。将 ASP.NET 配置为使用模拟功能,或者在 Windows 服务中使用编程模拟。

有关每种方法相对优点的详细信息,请参见第 8 章 ASP.NET 安全性中的访问网络资源。

将身份验证的凭据传递给远程对象

在客户端进程调用远程对象时,它使用代理来完成这一操作。这是一个本地对象,它公开一组与目标对象相同的方法。

指定客户端凭据

如果远程对象驻留在 ASP.NET 中并被配置为使用 Windows 身份验证,则必须使用通道的凭据属性来指定用于身份验证的凭据。如果没有明确设置凭据,就会在没有任何凭据的情况下调用远程对象。如果需要使用 Windows 身份验证,这将导致出现 HTTP 错误状态 401,即拒绝访问。

使用 DefaultCredentials

如果您要使用驻留远程对象代理(如果调用代理的线程使用模拟功能,则为当前线程令牌)的进程的凭据,则应该将通道的凭据属性设置为进程凭据缓存保存的 DefaultCredentials

可以在配置文件中指定是否使用 DefaultCredentials,或者通过编程方式设置凭据。

显式配置

在客户端应用程序配置文件(如果客户端应用程序是 ASP.NET Web 应用程序,则为 Web.config)中,将 <channel> 元素的 useDefaultCredentials 属性设置为 true,指定代理在与远程对象进行通信时应该使用 DefaultCredentials

<channel ref="http" useDefaultCredentials="true" />

编程配置

对于编程配置,请使用以下代码以编程方式确定是否使用 DefaultCredentials

IDictionary channelProperties;
channelProperties = ChannelServices.GetChannelSinkProperties(proxy);
channelProperties ["credentials"] = CredentialCache.DefaultCredentials;
使用特定凭据

在调用远程对象时,若要使用一组特定的身份验证凭据,请使用以下设置禁止在配置文件中使用默认凭据:

<channel ref="http" useDefaultCredentials="false" />

注意:编程设置会始终覆盖配置文件中的设置。

然后,使用以下代码来配置代理以使用特定的凭据:

IDictionary channelProperties =  
                         ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential("username", "password", "domain");
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
// 使用“协商”、“基本”、“摘要式”、“Kerberos”或“NTLM” 
// 替代“authenticationType”
credCache.Add(objectUri, "authenticationType", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;

请求特定的身份验证类型

按照上面所述,您应该使用 CredentialCache.Add 方法来请求特定的身份验证类型。避免直接使用 NetworkCredential 类,如以下代码所示:

IDictionary providerData = ChannelServices.GetChannelSinkProperties(yourProxy);
providerData["credentials"] = new NetworkCredential(uid, pwd);

在生产代码中应该避免出现这种情况,因为您无法控制远程对象主机使用的身份验证机制,因此也无法控制使用凭据的方式。

例如,您可能期望得到来自服务器的 Kerberos 或 NTLM 验证要求,但实际却可能收到一个基本身份验证要求。在这种情况下,以明文形式将提供的用户名和密码发送到服务器。

设置 preauthenticate 属性

可以将代理的 preauthenticate 属性设置为 true 或 false。如果将其设置为 true(如上述代码所示),则可以提供特定的身份验证凭据,以便通过初始请求传递 WWW-Authenticate HTTP 标头。这可避免 Web 服务器拒绝初始请求的访问,并在后续请求中执行身份验证。

使用 connectiongroupname 属性

如果 ASP.NET Web 应用程序连接到(驻留在 ASP.NET 中)远程组件并传递原调用方的安全性上下文(通过使用 DefaultCredentials 和模拟或通过设置显式凭据,如上所示),则应该在 Web 应用程序中设置通道的 connectiongroupname 属性。这用于防止未验证身份的新客户端重用到远程组件(该组件与以前的客户端身份验证凭据关联)的已验证身份的旧连接。在使用 HTTP KeepAlives 或出于 IIS 的性能考虑而启用身份验证持续功能时,会出现连接重用。

connectiongroupname 属性设置为能够区分调用方的标识符(例如,调用方的用户名)。

channelProperties["connectiongroupname"] = userName;

注意:如果没有通过 Web 应用程序将原调用方的安全性上下文传递给远程组件,而是使用固定标识(例如,Web 应用程序的 ASP.NET 进程标识)连接到远程组件,则您不需要设置 connectiongroupname 属性。在此方案中,连接安全性上下文在从一个调用方传递到下一个调用方时,保持不变。

下一版本的 .NET Framework 将支持基于调用代理对象的线程 SID 的连接池,如果 Web 应用程序正在模拟调用方,则它有助于解决上述问题。.NET Remoting 客户端支持连接池,但 Web 服务客户端不支持。

传递原调用方

本节介绍如何通过 ASP.NET Web 应用程序将原调用方的安全性上下文传递给远程应用程序服务器上 ASP.NET 驻留的远程组件。要在远程对象或后续下游子系统(例如,数据库)中支持每用户的授权,您可能需要完成上述操作。

在图 11.4 中,通过驻留在 ASP.NET Web 应用程序的前端 Web 服务器将原调用方(李华)的安全性上下文传递给远程应用程序服务器上 ASP.NET 中驻留的远程对象,并最终将其传递到后端数据库服务器。

 传递原调用方的安全性上下文

图 11.4
传递原调用方的安全性上下文

为了向远程对象传递凭据,远程对象客户端(此方案中的 ASP.NET Web 应用程序)必须配置该对象的代理,并明确地设置代理的 credentials 属性。有关说明,请参见本章前面的将身份验证的凭据传递给远程对象

注意:IPrincipal 对象无法跨越 .NET Remoting 边界进行传递。

可以使用两种方法来传递调用方的上下文:

传递默认凭据并使用 Kerberos 身份验证(和委派)。该方式要求您在 ASP.NET Web 应用程序内使用模拟,并用从被模拟调用方的安全性上下文中获得的 DefaultCredentials 来配置远程对象代理。

传递显式凭据并使用基本身份验证或窗体身份验证。该方式不要求在 ASP.NET Web 应用程序内使用模拟。相反,您可以通过编程方式,使用为 Web 应用程序提供的服务器变量(利用基本身份验证)或 HTML 窗体字段(利用窗体身份验证)中获取的显式凭据来配置远程对象代理。可以使用基本身份验证或窗体身份验证,以明文形式为服务器提供用户名和密码。

带有 Kerberos 委派的默认凭据

要使用 Kerberos 委派,所有计算机(服务器和客户端)都必须运行 Windows 2000 或更高版本。此外,必须将要委派的客户端帐户存储在 Active Directory® 目录服务中,并且不能将其标记为“敏感帐户,不能被委派”。

以下各表显示了在 Web 服务器和应用程序服务器上需要执行的配置步骤。

配置 Web 服务器

配置 IIS
步骤更多信息

禁用对 Web 应用程序的虚拟根目录的匿名访问

 

对 Web 应用程序的虚拟根目录启用 Windows 集成身份验证

如果客户端和服务器运行的是 Windows 2000 或更高版本,则可以对 Kerberos 身份验证进行协商。
注意:如果在 Windows 2000 上使用 Microsoft Internet Explorer 6,则它默认使用 NTLM 身份验证,而不是所需的 Kerberos 身份验证。要启用 Kerberos 委派,请参见 Microsoft 知识库文章 Q299838 Unable to Negotiate Kerberos Authentication after upgrading to Internet Explorer 6(升级到 Internet Explorer 6 后,无法协商 Kerberos 身份验证)。

配置 ASP.NET
步骤更多信息

将 ASP.NET Web 应用程序配置为使用 Windows 身份验证

编辑 Web 应用程序的虚拟目录下的 Web.config 文件。
将 <authentication> 元素设置为:

  
<authentication mode="Windows" />

配置 ASP.NET Web 应用程序的模拟

编辑 Web 应用程序的虚拟目录下的 Web.config 文件。
将 <identity> 元素设置为:

 
<identity impersonate="true" />

配置远程处理(客户端代理)
步骤更多信息

配置远程对象代理,以便将默认凭据用于对远程对象的所有调用

将如下条目添加到 Web.config 文件中:

<channel ref="http"  
	useDefaultCredentials="true" />
 

将从 Web 应用程序的
线程模拟令牌中获取凭据。

配置远程应用程序服务器

配置 IIS
步骤更多信息

禁用对 Web 应用程序的虚拟根目录的匿名访问

对 Web 应用程序的虚拟根目录启用 Windows 集成身份验证

 

配置 ASP.NET(远程对象主机)
步骤更多信息

将 ASP.NET 配置为使用 Windows 身份验证

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <authentication> 元素设置为:

<authentication mode="Windows" />

配置 ASP.NET 的模拟功能

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <identity> 元素设置为:

<identity impersonate="true" />

注意:只有在您要将原调用方的安全性上下文通过远程对象传递给下一个下游子系统(例如数据库)时,才需要执行本步骤。如果在此处启用了模拟功能,资源访问(本地和远程)就会使用模拟的原调用方的安全性上下文。如果您只要求在远程对象中对每个用户进行授权检查,则无需在此处启用模拟功能。

更多信息

有关 Kerberos 委派的详细信息,请参见本指南中的如何为 Windows 2000 实现 Kerberos 委派。

带有基本身份验证或窗体身份验证的显式凭据

作为 Kerberos 委派的一种替代方法,您可以在 Web 应用程序中使用基本身份验证或窗体身份验证来捕获客户端凭据,然后对远程对象使用基本身份验证(或者集成 Windows 身份验证)。

利用此方式,Web 应用程序可以使用客户端的明文凭据。可以通过远程对象代理将这些凭据传递给远程对象。为此,必须在 Web 应用程序中包含代码以检索客户端凭据并配置远程对象代理。

基本身份验证

使用基本身份验证,Web 应用程序可在服务器变量中使用原调用方的凭据。以下代码说明如何检索这些凭据并配置远程对象代理:

// 检索客户端的凭据(可通过基本身份验证进行)
string pwd = Request.ServerVariables["AUTH_PASSWORD"];
string uid = Request.ServerVariables["AUTH_USER"];
// 将凭据与远程对象代理相关联
IDictionary channelProperties =  
                         ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential(uid, pwd);
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
credCache.Add(objectUri, "Basic", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;

注意:上述代码中的 NetworkCredential 构造函数是随用户 ID 和密码提供的。要避免对域名进行硬编码,在配置基本身份验证时,可以在 IIS 中的 Web 服务器上配置默认域。

窗体身份验证

使用窗体身份验证,Web 应用程序可在窗体各个字段中(而不是在服务器变量中)使用原调用方的凭据。在这种情况下,请使用以下代码:

// 从登录窗体检索客户端的凭据
string pwd = txtPassword.Text;
string uid = txtUid.Text;
// 将凭据与远程对象代理相关联
IDictionary channelProperties =  
                         ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential(uid, pwd);
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
credCache.Add(objectUri, "Basic", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;

以下各表显示了在 Web 服务器和应用程序服务器上需要执行的配置步骤。

配置 Web 服务器

配置 IIS
步骤更多信息

要使用基本身份验证,请禁用对您 Web 应用程序的虚拟根目录的匿名访问,并选择基本身份验证

-或-

要使用窗体身份验证,请启用匿名访问

基本身份验证和窗体身份验证都应和 SSL 配合使用,才能保护通过网络传送的明文凭据。如果您使用基本身份验证,则应该将 SSL 用于所有页面(而不仅仅是初始登录页面),因为在每个请求中都传递基本身份验证凭据。类似地,如果您使用窗体身份验证,则应该将 SSL 用于所有页面,以保护初始登录中的明文凭据以及在后续请求中传递的身份验证票证。

配置 ASP.NET
步骤更多信息

如果您使用基本身份验证,则将您的 ASP.NET Web 应用程序配置为使用 Windows 身份验证

-或-

如果您使用窗体身份验证,则将您的 ASP.NET Web 应用程序配置为使用窗体身份验证

编辑您的 Web 应用程序的虚拟目录下的 Web.config 文件。将 <authentication> 元素设置为:

  <authentication mode="Windows" />

-或-

编辑您的 Web 应用程序的虚拟目录下的 Web.config 文件。将 <authentication> 元素设置为:

  <authentication mode="Forms" />

禁用 ASP.NET Web 应用程序内的模拟功能

编辑您的 Web 应用程序的虚拟目录下的 Web.config 文件。将 <identity> 元素设置为:

<identity impersonate="false" />

注意:这相当于没有 <identity> 元素。因为通过远程对象代理将用户凭据明确传递给远程对象,所以不需要使用模拟功能。

配置远程处理(客户端代理)
步骤更多信息

配置远程处理代理,不要将默认凭据用于对远程对象的所有调用

将如下条目添加到 Web.config 文件中:

<channel ref="http"
         useDefaultCredentials="false" />

 

您不希望使用默认凭据(因为将 Web 应用程序配置为不使用模拟,因此,这将导致使用 ASP.NET 进程标识的安全性上下文)。

编写代码,以便在远程对象代理中捕获和明确地设置凭据

请参考前面的代码片段。

配置应用程序服务器

配置 IIS
步骤更多信息

禁用对应用程序的虚拟根目录的匿名访问

 

启用基本身份验证

注意:通过在应用程序服务器(远程对象)上使用基本身份验证,远程对象可以将原调用方的安全性上下文传递到数据库(因为调用方的用户名和密码采用明文形式,并且可以用来响应来自数据库服务器的网络身份验证质询)。如果不需要将原调用方的安全性上下文传递到远程对象以外,则考虑在应用程序服务器上将 IIS 配置为使用 Windows 集成身份验证,因为这可提供更高的安全性(不通过网络传递凭据,并且不给应用程序提供凭据)。

配置 ASP.NET(远程对象主机)
步骤更多信息

将 ASP.NET 配置为使用 Windows 身份验证

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <authentication> 元素设置为:

<authentication mode="Windows" />

配置 ASP.NET 的模拟功能

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <identity> 元素设置为:

<identity impersonate="true" />

注意:只有在您要将原调用方的安全性上下文通过远程对象传递给下一个下游子系统(例如数据库)时,才需要执行本步骤。如果在此处启用了模拟功能,资源访问(本地和远程)就会使用模拟的原调用方的安全性上下文。如果您只要求在远程对象中对每个用户进行授权检查,则无需在此处启用模拟功能。

受信任的子系统

受信任的子系统模型提供了一种替代(且更易于实现的)方式来传递原调用方的安全性上下文。在该模型中,远程对象主机和 Web 应用程序之间存在信任边界。远程对象首先信任 Web 应用程序对调用方正确地进行身份验证和授权,然后才允许向远程对象发送请求。在远程对象主机中不对原调用方进行任何身份验证。远程对象主机对 Web 应用程序用来与远程对象通信的固定受信任标识进行身份验证。在大多数情况下,这是 ASP.NET Web 应用程序的进程标识。

图 11.5 显示了受信任的子系统模型。该图还显示了两种可能的配置。第一种配置使用 ASP.NET 主机和 HTTP 通道,而第二种配置使用 Windows 服务主机和 TCP 通道。

 受信任的子系统模型

图 11.5
受信任的子系统模型

传递调用方标识

如果您使用的是受信任的子系统模型,则可能仍然需要传递原调用方的标识(名称,不是安全性上下文),例如,用于在数据库中进行审核。

通过使用可用于从数据库检索用户特定数据的方法、存储过程参数和受信任的查询参数(如下面的示例所示),可以在应用程序级传递该标识。

SELECT x,y,z FROM SomeTable WHERE UserName = "李华"

选择主机

受信任的子系统模型意味着远程对象主机不对原调用方进行身份验证。但是,它仍需对其中间客户端(此方案中的 ASP.NET Web 应用程序)进行身份验证(和授权),以防止未经授权的应用程序向远程对象发出请求。

如果您在 ASP.NET 中驻留对象并使用 HTTP 通道,则可以使用 Windows 集成身份验证对 ASP.NET Web 应用程序进程标识进行身份验证。

如果您在 Windows 服务中驻留对象,则可以使用具有更高性能的 TCP 通道,但是该通道不提供身份验证功能。在此方案中,可以在 Web 服务器和应用程序服务器之间使用 IPSec。可以制订只允许 Web 服务器与应用程序服务器进行通信的 IPSec 策略。

配置步骤

以下各表显示了在 Web 服务器和应用程序服务器上需要执行的配置步骤。

配置 Web 服务器

配置 IIS
步骤更多信息

配置 IIS 身份验证

Web 应用程序可以使用任何形式的验证方法来验证原调用方的身份。

配置 ASP.NET
步骤更多信息

配置身份验证并确保禁用模拟功能

编辑 Web 应用程序的虚拟目录下的 Web.config 文件。
将 <authentication> 元素设置为“Windows”、“Forms”
或“Passport”。

<authentication mode="Windows|Forms|Passport" />

将 <identity> 元素设置为:

identity impersonate="false" />

(或者删除 <identity> 元素)

重置用于运行 ASP.NET 的 ASPNET 帐户的密码,或者创建一个权限最少的域帐户来运行 ASP.NET,并在 Web.config 文件内的 <processModel> 元素上指定帐户详细信息

有关如何从
ASP.NET 访问网络资源(包括远程对象)以及
选择和配置
ASP.NET 进程帐户的详细信息,请参见第 8 章 ASP.NET 安全性中的访问网络资源和
ASP.NET 的进程标识。

配置远程处理(客户端代理)
步骤更多信息

配置远程处理代理,以便将默认凭据用于对远程对象的所有调用

将如下条目添加到 Web.config 文件中:

<channel ref="http"  
	useDefaultCredentials="true" />

由于 Web 应用程序没有使用模拟,因此,如果使用
默认凭据,就会导致将 ASP.NET
进程标识用于对远程对象的所有调用。

配置应用程序服务器

配置 IIS
步骤更多信息

禁用对应用程序的虚拟根目录的匿名访问

启用 Windows 集成身份验证

 

配置 ASP.NET(远程对象主机)
步骤更多信息

将 ASP.NET 配置为使用 Windows 身份验证

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <authentication> 元素设置为:

<authentication mode="Windows" />

禁用模拟功能

编辑该应用程序的虚拟目录下的 Web.config 文件。将 <identity> 元素设置为:

<identity impersonate="false" />

使用 Windows 服务主机

如果使用的是 Windows 服务主机进程,则必须创建一个 Windows 帐户以运行该服务。远程对象将使用该帐户提供的安全性上下文来访问所有本地和远程资源。

要访问远程 Microsoft SQL Server™ 数据库(利用 Windows 身份验证),您可以使用权限最少的域帐户;也可以使用本地帐户,然后在数据库服务器上创建一个重复帐户(具有相同的用户名和密码)。

安全通信

安全通信是指在通过网络传送消息时确保消息的完整性和机密性。可以使用基于平台的方法来保护通信的安全并使用 SSL 或 IPSec;也可以使用消息级方法并开发自定义的加密接收,以便对整个消息或消息的选定部分进行加密。

平台级选项

可以考虑两个平台级选项以保护在客户端和远程组件之间传送的数据安全:

SSL

IPSec

如果远程对象驻留在 ASP.NET 中,则可以使用 SSL 来保护客户端和服务器之间的通信通道。这要求驻留远程对象的计算机具有服务器身份验证证书。

如果远程对象驻留在 Windows 服务中,则可以在客户端和主机(服务器)之间使用 IPSec,也可以开发自定义的加密接收。

消息级选项

由于 .NET Remoting 体系结构具有可扩展性,因此,您可以开发自定义接收并将其插入到处理管道中。要提供安全的通信,可以开发自定义接收,以便对发送到和来自远程对象的消息数据进行加密和解密。

这种方法的优点是您可以有选择地加密消息的一部分。这与平台级方法正好相反,平台级方法是对客户端和服务器之间发送的所有数据进行加密。

更多信息

有关 SSL 和 IPSec 的详细信息,请参见第 4 章安全通信。

选择主机进程

要远程访问的对象必须在主机可执行文件中运行。主机侦听传入请求,并向对象发出调用。所选的主机类型会影响称为“通道”的消息传输机制。选择的通道类型影响身份验证、授权、安全通信和解决方案的性能。

HTTP 通道提供更好的安全性选项,但 TCP 通道提供更高的性能。

可以使用以下主要选项来驻留远程对象:

驻留在 ASP.NET 中

驻留在 Windows 服务中

驻留在控制台应用程序中

建议

从安全的角度出发,要充分利用 ASP.NET 和 IIS 提供的安全基础结构,建议将远程对象驻留在 ASP.NET 中。这要求客户端通过 HTTP 通道与远程对象进行通信。驻留在 ASP.NET 中的远程对象可以使用 ASP.NET 和 IIS 身份验证、授权和安全通信功能。

如果主要关心性能(而不是安全性)问题,则考虑将远程对象驻留在 Windows 服务中。

驻留在 ASP.NET 中

在将远程对象驻留在 ASP.NET 中时:

使用 HTTP 协议可访问该对象。

它具有一个可通过 URL 访问的终结点。

它位于 Aspnet_wp.exe 辅助进程内的应用程序域中。

它继承 IIS 和 ASP.NET 提供的安全功能。

优点

如果将远程对象驻留在 IIS 中,则您可以获得以下优势:

直接使用 IIS 和 ASP.NET 提供的身份验证、授权和安全通信功能。

可以使用 IIS 的审核功能。

ASP.NET 辅助进程始终运行。

通过使用 Machine.config 中的 <processModel> 元素,对驻留的可执行文件进行更严格的控制。可以控制线程管理、容错性和内存管理等等。

可以在远程对象前面创建 Web 服务外层。

缺点

如果使用 ASP.NET 驻留远程对象,则应该了解它的以下缺点:

它要求使用的 HTTP 通道比 TCP 通道慢。

ASP.NET 不加载用户配置文件。多种加密技术(包括 DPAPI)可能需要使用用户配置文件。

如果从 ASP.NET Web 应用程序中运行的代码访问对象,则可能需要使用基本身份验证。

驻留在 Windows 服务中

如果将远程对象驻留在 Windows 服务中,则在服务进程内包含的应用程序域中激活远程对象。您不能使用 HTTP 通道,而必须使用 TCP 通道。TCP 通道支持以下安全功能:

身份验证功能

您必须提供自定义的身份验证解决方案。选项包括:

使用 SSPI 的基本身份验证服务。可以创建使用 Windows SSPI 凭据和上下文管理 API 的通道接收,对调用方进行身份验证并有选择地模拟调用方。该通道接收位于 TCP 通道的顶端。配合 TCP 通道使用的 SSPI 允许客户端和服务器交换身份验证信息。在进行身份验证后,客户端和服务器可以发送消息并确保消息的机密性和完整性。

使用支持身份验证的基本传输(例如,命名管道)。命名管道通道将命名管道用作传输机制。它给调用方提供了身份验证功能,并且还在管道中引入基于 Windows ACL 的安全功能以及调用方的模拟功能。

授权功能
仅当实现自定义的身份验证解决方案后,才能使用授权功能。

如果您能够模拟用户(例如,通过使用基本的命名管道传输),则可以使用 WindowsPrincipal.IsInRole

如果您能够创建 IPrincipal 对象来代表已验证身份的客户端,则可以使用 .NET 角色(通过主体权限要求和使用 IPrincipal.IsInRole 进行明确的角色检查)。

安全通信功能

您有两个选项:

使用 IPSec 保护客户端和服务器之间的数据传输安全。

创建执行非对称加密的自定义通道接收。此选项将在本章后面讲述。

优点

如果将远程对象驻留在 Windows 服务中,则可以获得以下优势:

对主机进程进行严格的激活控制。

继承 Windows 服务体系结构的优点。

无需在应用程序的中间层引入 IIS。

自动加载用户配置文件。

性能与客户端使用二进制编码数据通过 TCP 通道进行通信时相当。

缺点

如果使用 Windows 服务来驻留远程对象,则应该了解它的以下缺点:

必须提供自定义的身份验证和授权解决方案。

必须提供安全的通信解决方案。

必须提供审核解决方案。

驻留在控制台应用程序中

如果将远程对象驻留在控制台应用程序中,则在控制台应用程序进程内包含的应用程序域中激活远程对象。您不能使用 HTTP 通道,而必须使用 TCP 通道。

建议在生产解决方案中不要使用这种方法。

优点

虽然这种方法没有多少优点,但它在中间层的确不需要使用 IIS。不过,仅建议在开发和测试环境中使用这种方法,不要在生产环境中使用。

缺点

如果将远程对象驻留在自定义的可执行文件中,则应该了解它的以下缺点:

主机必须手动启动,并且在交互式登录会话中运行(不建议使用)。

没有容错功能。

必须提供自定义的身份验证和授权功能。

没有审核功能。

远程处理与 Web 服务的比较

.NET 提供多种不同的方法使客户端能够与远程对象进行通信,其中包括使用 Web 服务。

如果需要异类系统之间具有互操作性,则最好选择使用开放式标准(例如 SOAP、XML 和 HTTP)的 Web 服务方法。另一方面,如果您正在创建服务器到服务器的 Intranet 解决方案,则远程处理组件可提供以下功能:

由于可以远程控制任何 .NET 类型(包括使用 Microsoft C#® 开发工具和 Microsoft Visual Basic® .NET 开发系统创建的自定义类型),因此各种对象保持不变。
这包括类、类层次结构、接口、字段、属性、方法和委派、数据集、哈希值表等等。

可以按值和按引用来封送对象。

对象生命周期管理是基于租期进行的。

高性能,尤其是使用 TCP 通道和二进制格式化程序时。

它允许您使用网络负载平衡功能构建负载平衡的中间层。

表 11.2: 远程处理和 Web 服务的主要差别

远程处理Web 服务

全状态或无状态,基于租期的对象生命周期管理

所有方法调用都是无状态的

不需要 IIS
(但是出于安全方面的考虑,建议驻留在 IIS/ASP.NET 中)

必须在服务器上安装 IIS

支持所有的托管类型

支持数量有限的数据类型。有关
ASP.NET Web 服务支持的类型的详细信息,请参见 MSDN 上的 .NET Framework Developer's Guide(.NET Framework 开发人员指南)。

可以按引用或按值传递对象

无法传递对象

包含可扩展的体系结构,并不
限于 HTTP 或 TCP 传输

限于 HTTP 上的 XML

可以将自定义的处理接收插入到
消息处理管道中

无法修改消息

SOAP 实现方式有所限制,并且
只能使用 RPC 编码

SOAP 实现方式可以使用 RPC 或
文档编码,并且可以实现与
其他 Web 服务平台的完全
互操作。
有关详细信息,请参阅 MSDN 文章
Distributed Application Communication(分布式应用程序通信)中的“Message Formatting and Encoding”(消息格式设置和编码)一节。

紧密集成

松散集成

总结

.NET Remoting 自身不提供安全模型。然而,通过将远程对象驻留在 ASP.NET 中并使用 HTTP 通道进行通信,远程对象可以使用 IIS 和 ASP.NET 提供的基本安全服务。比较而言,TCP 通道和自定义的主机可执行文件能够提供更高的性能,但这种组合不提供内置的安全功能。

若要对客户端进行身份验证,请使用 HTTP 通道,在 ASP.NET 中驻留对象,以及在 IIS 中禁用匿名访问。

如果您不担心客户端身份验证问题,请使用 TCP 通道,它可以提供更高的性能。

如果您使用 TCP 通道,请使用 IPSec 保护客户端和服务器之间的通信通道。使用 SSL 来保护 HTTP 通道。

如果您需要对远程资源进行受信任的调用,请将组件驻留在 Windows 服务中,而不是驻留在控制台应用程序中。

IPrincipal 对象无法跨越 .NET Remoting 边界传递。可以考虑实现您自己的 IPrincipal 类(可以进行序列化)。如果您执行上述操作,则要注意,未经授权的客户端可以很容易地骗过 IPrincipal 对象并将它发送给远程对象。另外,如果您在远程处理过程中实现了您自己的 IPrincipal 类,则要慎用 IlogicalThreadAffinitive

始终不要向 Internet 公开远程对象。在这种情况下,请使用 Web 服务。
应该仅在 Intranet 中使用 .NET Remoting。应该使用内部方式从 Web 应用程序访问对象。即使对象驻留在 ASP.NET 中,也不要向 Internet 客户端公开它们,因为客户端必须是 .NET 客户端。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值