利用集成 windows身份验证在 IIS中承载此服务,以保护服务器

错误信息: 利用集成 windows身份验证在 IIS中承载此服务,以保护服务器

错误原因:ChannelServices.RegisterChannel(new HttpChannel(9999),true); 使用了HttpChannel ,并且注册时用了 ensureSecurity=True

详细原因:转载 http://blog.csdn.net/blue_sky_blue_heart/article/details/1130914


在进行Remoting开发过程中,一种流行的做法是将诸如对象激活方式,注册通道的类型,端口信息等写在配置文件中,然后使用RemotingConfiguration.Configure (String)方法读取这些信息并完成远程调用的配置。此时你会发现,.NET编译器提示该方法已经过期,推荐使用RemotingConfiguration.Configure (String, Boolean),这是.NET FrameWork2.0版中新增的方法。后者与前者的区别仅在于多了一个参数,完整的表示形式为:
public static void Configure ( string filename, bool ensureSecurity )
那么后面的这个ensureSecurity布尔型参数究竟有什么用呢。Msdn上给出的解释非常简单,如下:
ensureSecurity
如果启用安全性,则为 true;否则为 false。
显然不满足安全性要求会抛出一个SecurityException异常来,但是如何启用安全性,处理针对谁的安全性都没有详细的说明。在Google上搜索了一下,发现大家还热衷于使用那个过时的版本,很少有用public static void Configure ( string filename, bool ensureSecurity )这种形式的,至于相关说明就更是少之又少。下面是用.Net Reflecter工具看到的Configure ( string filename, bool ensureSecurity )内部实现代码:

        

[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration)]
public static void Configure(string filename, bool ensureSecurity)
{
      RemotingConfigHandler.DoConfiguration(filename, ensureSecurity);
      RemotingServices.InternalSetRemoteActivationConfigured();
}

跟踪到DoConfiguration()方法中去,如下:

internal static void DoConfiguration(string filename, bool ensureSecurity)
{
      RemotingConfigHandler.LoadMachineConfigIfNecessary();
      RemotingXmlConfigFileData data1 = RemotingConfigHandler.LoadConfigurationFromXmlFile(filename);
      if (data1 != null)
      {
            RemotingConfigHandler.ConfigureRemoting(data1, ensureSecurity);
      }
}

继续探查RemotingConfigHandler的ConfigureRemoting

private static void ConfigureRemoting(RemotingXmlConfigFileData configData, bool ensureSecurity)
{
      try
      {
            string text1 = configData.ApplicationName;
            if (text1 != null)
            {
                  RemotingConfigHandler.ApplicationName = text1;
            }
            if (configData.CustomErrors != null)
            {
                  RemotingConfigHandler._errorMode = configData.CustomErrors.Mode;
            }
            RemotingConfigHandler.ConfigureChannels(configData, ensureSecurity);
            if (configData.Lifetime != null)
            {
                  if (configData.Lifetime.IsLeaseTimeSet)
                  {
                        LifetimeServices.LeaseTime = configData.Lifetime.LeaseTime;
                  }
                  if (configData.Lifetime.IsRenewOnCallTimeSet)
                  {
                        LifetimeServices.RenewOnCallTime = configData.Lifetime.RenewOnCallTime;
                  }
                  if (configData.Lifetime.IsSponsorshipTimeoutSet)
                  {
                        LifetimeServices.SponsorshipTimeout = configData.Lifetime.SponsorshipTimeout;
                  }
                  if (configData.Lifetime.IsLeaseManagerPollTimeSet)
                  {
                        LifetimeServices.LeaseManagerPollTime = configData.Lifetime.LeaseManagerPollTime;
                  }
            }
            RemotingConfigHandler._bUrlObjRefMode = configData.UrlObjRefMode;
            RemotingConfigHandler.Info.StoreRemoteAppEntries(configData);
            RemotingConfigHandler.Info.StoreActivatedExports(configData);
            RemotingConfigHandler.Info.StoreInteropEntries(configData);
            RemotingConfigHandler.Info.StoreWellKnownExports(configData);
            if (configData.ServerActivatedEntries.Count > 0)
            {
                  ActivationServices.StartListeningForRemoteRequests();
            }
      }
      catch (Exception exception1)
      {
            throw new RemotingException(string.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Config_ConfigurationFailure"), new object[] { exception1 }));
      }
}

在此方法中继续寻找使用那个ensureSecurity参数的地方,显然里面是要使用该参数配置通道,再跟进去

private static void ConfigureChannels(RemotingXmlConfigFileData configData, bool ensureSecurity)
{
      RemotingServices.RegisterWellKnownChannels();
      foreach (RemotingXmlConfigFileData.ChannelEntry entry1 in configData.ChannelEntries)
      {
            if (!entry1.DelayLoad)
            {
                  IChannel channel1 = RemotingConfigHandler.CreateChannelFromConfigEntry(entry1);
                  ChannelServices.RegisterChannel(channel1, ensureSecurity);
            }
            else
            {
                  RemotingConfigHandler._delayLoadChannelConfigQueue.Enqueue(new DelayLoadClientChannelEntry(entry1, ensureSecurity));
            }
      }
}

这时我们看到了
ChannelServices.RegisterChannel(channel1, ensureSecurity);
通常我们会用ChannelServices.RegisterChannel(channel1),但此时.NET会提示我们该方法也已过期。原来,
RemotingConfiguration.Configure (String, Boolean)其实就是ChannelServices.RegisterChannel(channel1, ensureSecurity)方法的一个最上层包装罢了,它要将用户设置的ensureSecurity参数值一层层的传递到ChannelServices.RegisterChannel方法中去。在Msdn中我们可以找到对该方法的第二个参数的说明:
ensureSecurity
true ensures that security is enabled; otherwise false. Setting the value to false will not nullify the security setting done on the TCP or IPC channel. For details, see Remarks.
Remarks
……
If the ensureSecurity parameter is set to true, the remoting system determines whether the channel implements ISecurableChannel, and if so, enables encryption and digital signatures. An exception is thrown if the channel does not implement ISecurableChannel. Note: 
Setting ensureSecurity to true throws a RemotingException for  TcpServerChannel on win98 (Since secure tcp channel is not supported on wi9x)  , and for Http Server Channel on all platforms (Users need to host service in IIS if they want secure http channel).
这下我们因该明白了ensureSecurity参数其实是用来设置注册通道安全性的。


分别使用HttpChannel和TcpChannel的例子

static void Main(string[] args)
        {
            Console.WriteLine("Host Started.");
            //Channel Registeration
            HttpChannel c = new HttpChannel(3200);
            ChannelServices.RegisterChannel(c,true);
            //Type Registeration-Use server-activated object(SAO)
            //Type is sepecified as (namespace.class)
            Type ServerType = typeof(SimpleServer.MessageManager);
            RemotingConfiguration.RegisterWellKnownServiceType(
                ServerType,//Type of object
                "MyObject",//Arbitrary name
                WellKnownObjectMode.SingleCall);
            Console.Read(); //Keep host running
        }
 
static void Main()
        {
            Console.WriteLine("Host Started.");
            //Channel Registration
            TcpChannel c = new TcpChannel(3200);
            //c.IsSecured = true;
            ChannelServices.RegisterChannel(c, true);
            //Type Registeration
            Type ServerType = typeof(MessageManager);
            RemotingConfiguration.RegisterWellKnownServiceType(
                ServerType,    //Type of object
                "MyObject",    //Arbitrary name
                WellKnownObjectMode.Singleton);
            Console.Read();
           
        }

运行第一个例子,马上会抛出一个RemotingException: “利用集成 Windows 身份验证在 IIS 中承载此服务,以保护服务器”,而运行第二个例子,却不会有任何问题,why?
这是因为:

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



原来,Remoting没有自己的安全模型,客户端(代理)和服务器(远程对象)之间的身份验证和授权是通过通道和主机进程执行的。可以组合使用以下的主机和通道:
1、自定义的可执行文件和TCP通道。这种组合不提供任何内置的安全功能。
2、 ASP.NET和HTTP通道。这种组合通过基本的ASP.NET和IIS安全功能提供身份验证和授权。
在上面的第一个例子中,由于我们并没有提供相应的身份验证凭证,所以会抛出那样的异常,显然是IIS进行身份验证时出现错误。而在第二个例子中,由于对TCP通道没有设置安全功能,所以将ensureSecurity设置为True和False都是一样的,即都可以正常的工作。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值