做项目不得不考虑安全问题,但是在Remoting应用中我似乎没有找到象WebService那样现成可用的防止非授权人员随意调用的方法和验证安全机制。当然,简单一点的可以通过Remoting客户端传输一些验证代码,然后在服务端验证这些代码的合法性,以实现是否安全授权调用,但是总觉得这样比较麻烦。我也见有些人主动把客户端的IP地址获取后主动送入到Remotin g服务端验证以便识别是否合法,其实原理跟上面的是一样的道理,我觉得这样传送很容易让别人仿造一些数据送入,从而轻易获得合法调用。当然以上数据可以通过把数据特殊的加密和解密也能得到比较好的安全性。在这里我是想介绍另外一种安全机制,即构建Remoting“防火墙”。
    
    做项目不得不考虑安全问题,但是在Remoting应用中我似乎没有找到象WebService那样现成可用的防止非授权人员随意调用的方法和验证安全机制。当然,简单一点的可以通过Remoting客户端传输一些验证代码,然后在服务端验证这些代码的合法性,以实现是否安全授权调用,但是总觉得这样比较麻烦。我也见有些人主动把客户端的IP地址获取后主动送入到Remotin g服务端验证以便识别是否合法,其实原理跟上面的是一样的道理,我觉得这样传送很容易让别人仿造一些数据送入,从而轻易获得合法调用。当然以上数据可以通过把数据特殊的加密和解密也能得到比较好的安全性。在这里我是想介绍另外一种安全机制,即构建Remoting“防火墙”。
其实我所说的Remoting“防火墙”也是最基本的。由于Remoting的TcpChannel没有提供内建的认证机制,所以没有现成获取客户端的方法,我们可以在Remoting Server端注册上自定义的Server Channel Sink,通过Transport Headers来获取request的IP,以下是自定义的Server Channel Sink类的代码,(注:原代码不是我写的,原出处我忘记了,所以无法标注来源)


1 using System;
using System;
2 using System.Collections;
using System.Collections;
3 using System.IO;
using System.IO;
4 using System.Runtime.Remoting;
using System.Runtime.Remoting;
5 using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Messaging;
6 using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels;
7 using System.Threading;
using System.Threading;
8 using System.Net;
using System.Net;
9
10
11 namespace Colorful.RemoteObject
namespace Colorful.RemoteObject
12

 {
{
13 public class ClientIPServerSinkProvider : IServerChannelSinkProvider
    public class ClientIPServerSinkProvider : IServerChannelSinkProvider
14
 
     {
{
15
16 private IServerChannelSinkProvider next = null;
        private IServerChannelSinkProvider next = null;
17
18 public ClientIPServerSinkProvider()
        public ClientIPServerSinkProvider()
19
 
         {
{
20 }
        }
21
22 public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData)
        public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData)
23
 
         {
{
24 }
        }
25
26 public void GetChannelData(IChannelDataStore channelData)
        public void GetChannelData(IChannelDataStore channelData)
27
 
         {
{
28 }
        }
29
30 public IServerChannelSink CreateSink(IChannelReceiver channel)
        public IServerChannelSink CreateSink(IChannelReceiver channel)
31
 
         {
{
32 IServerChannelSink nextSink = null;
            IServerChannelSink nextSink = null;
33
34 if (next != null)
            if (next != null)
35
 
             {
{
36 nextSink = next.CreateSink(channel);
                nextSink = next.CreateSink(channel);
37 }
            }
38
39 return new ClientIPServerSink(nextSink);
            return new ClientIPServerSink(nextSink);
40 }
        }
41
42
43
44 public IServerChannelSinkProvider Next
        public IServerChannelSinkProvider Next
45
 
         {
{
46
 get
            get  { return next; }
{ return next; }
47
 set
            set  { next = value; }
{ next = value; }
48 }
        }
49 }
    }
50
51 public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase
    public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase
52
 
     {
{
53 private IServerChannelSink _next;
        private IServerChannelSink _next;
54
55 public ClientIPServerSink(IServerChannelSink next)
        public ClientIPServerSink(IServerChannelSink next)
56
 
         {
{
57 _next = next;
            _next = next;
58 }
        }
59
60 public void AsyncProcessResponse(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers, System.IO.Stream stream)
        public void AsyncProcessResponse(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers, System.IO.Stream stream)
61
 
         {
{
62 }
        }
63
64 public Stream GetResponseStream(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers)
        public Stream GetResponseStream(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers)
65
 
         {
{
66 return null;
            return null;
67 }
        }
68
69 public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, out System.Runtime.Remoting.Messaging.IMessage responseMsg, out System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
        public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, out System.Runtime.Remoting.Messaging.IMessage responseMsg, out System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
70
 
         {
{
71 if (_next != null)
            if (_next != null)
72
 
             {
{
73 IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
                IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
74
75 CallContext.SetData("IP", ip);
                CallContext.SetData("IP", ip);
76
77 ServerProcessing spres = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                ServerProcessing spres = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
78
79 return spres;
                return spres;
80 }
            }
81 else
            else
82
 
             {
{
83 responseMsg = null;
                responseMsg = null;
84
85 responseHeaders = null;
                responseHeaders = null;
86
87 responseStream = null;
                responseStream = null;
88
89 return new ServerProcessing();
                return new ServerProcessing();
90 }
            }
91 }
        }
92
93
94
95 public IServerChannelSink NextChannelSink
        public IServerChannelSink NextChannelSink
96
 
         {
{
97
 get
            get  { return _next; }
{ return _next; }
98
 set
            set  { _next = value; }
{ _next = value; }
99 }
        }
100 }
    }
101 }
}
102 以下是远程对象主程序代码
以下是远程对象主程序代码


1 class Program
class Program
2
 
     {
{
3 static void Main(string[] args)
        static void Main(string[] args)
4
 
         {
{
5 int TcpPort = ConfigInfo.RemoteSocketPort;
            int TcpPort = ConfigInfo.RemoteSocketPort;
6 BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
            BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
7 provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
            provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
8 //实例化自定义的Server Channel Sink类
            //实例化自定义的Server Channel Sink类
9 Colorful.RemoteObject.ClientIPServerSinkProvider IpInjProvider = new Colorful.RemoteObject.ClientIPServerSinkProvider();
            Colorful.RemoteObject.ClientIPServerSinkProvider IpInjProvider = new Colorful.RemoteObject.ClientIPServerSinkProvider();
10 provider.Next = IpInjProvider;//加入接收链
            provider.Next = IpInjProvider;//加入接收链
11 
            
12 IDictionary props = new Hashtable();
            IDictionary props = new Hashtable();
13 props["port"] = TcpPort;
            props["port"] = TcpPort;
14 
            
15 TcpChannel chan1 = new TcpChannel(props,null,provider);
            TcpChannel chan1 = new TcpChannel(props,null,provider);
16
17 ChannelServices.RegisterChannel(chan1, false);
            ChannelServices.RegisterChannel(chan1, false);
18
19 LifetimeServices.LeaseTime = TimeSpan.Zero;//租用周期
            LifetimeServices.LeaseTime = TimeSpan.Zero;//租用周期
20 RemotingConfiguration.RegisterWellKnownServiceType
            RemotingConfiguration.RegisterWellKnownServiceType
21 (
                (
22 typeof(Colorful.RemoteObject.Server),
                typeof(Colorful.RemoteObject.Server),
23 ConfigInfo.RemoteSocketURI,
                ConfigInfo.RemoteSocketURI,
24 WellKnownObjectMode.Singleton
                WellKnownObjectMode.Singleton
25 );
                );
26 Console.WriteLine(DateTime.Now.ToString() + "服务通道注册成功!等待数据服务请求
            Console.WriteLine(DateTime.Now.ToString() + "服务通道注册成功!等待数据服务请求
 ");
");            
27
28 Console.ReadLine();
            Console.ReadLine();
29 }
        }
30 }
然后通过配置许可的IP地址XML文件,读取XML验证IP地址列表,然后调用以下函数验证客户端调用的合法性,非授权的IP拒绝访问
    }
然后通过配置许可的IP地址XML文件,读取XML验证IP地址列表,然后调用以下函数验证客户端调用的合法性,非授权的IP拒绝访问

 验证客服端的合法性#region 验证客服端的合法性
 验证客服端的合法性#region 验证客服端的合法性

 /**//// <summary>
        /**//// <summary>
 /// 检查Remoting客户端的合法性
        /// 检查Remoting客户端的合法性
 /// </summary>
        /// </summary>
 /// <returns></returns>
        /// <returns></returns>
 public bool CheckRemotingClient()
        public bool CheckRemotingClient()

 
         {
{
 IPAddress data = (IPAddress)CallContext.GetData("ClientIPAddress");
            IPAddress data = (IPAddress)CallContext.GetData("ClientIPAddress");

 if (clientIPAddress.ContainsKey(data))
            if (clientIPAddress.ContainsKey(data))

 
             {
{
 string msg = "接受远程地址:" + data.ToString() + "的服务请求";
                string msg = "接受远程地址:" + data.ToString() + "的服务请求";
 Console.WriteLine(msg);
                Console.WriteLine(msg);
 return true;
                return true;
 }
            }
 else
            else

 
             {
{
 string msg = "远程地址:" + data.ToString() +"不在许可范围内,服务请求被拒绝";
                string msg = "远程地址:" + data.ToString() +"不在许可范围内,服务请求被拒绝";
 Console.WriteLine(msg);
                Console.WriteLine(msg);
 SQL2005DAL.CommDAL.WriteLogFile("RemotingClientTrace", msg, "Warring", false);
                SQL2005DAL.CommDAL.WriteLogFile("RemotingClientTrace", msg, "Warring", false);
 return false;
                return false;
 }
            }

 }
        }
 #endregion
基本上就这么多,详细内容,请参看VB.NET Remoting技术手册,其他安全请参看.NET Remoting 安全性
        #endregion
基本上就这么多,详细内容,请参看VB.NET Remoting技术手册,其他安全请参看.NET Remoting 安全性
其实我所说的Remoting“防火墙”也是最基本的。由于Remoting的TcpChannel没有提供内建的认证机制,所以没有现成获取客户端的方法,我们可以在Remoting Server端注册上自定义的Server Channel Sink,通过Transport Headers来获取request的IP,以下是自定义的Server Channel Sink类的代码,(注:原代码不是我写的,原出处我忘记了,所以无法标注来源)


1
 using System;
using System;2
 using System.Collections;
using System.Collections;3
 using System.IO;
using System.IO;4
 using System.Runtime.Remoting;
using System.Runtime.Remoting;5
 using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Messaging;6
 using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels;7
 using System.Threading;
using System.Threading;8
 using System.Net;
using System.Net;9

10

11
 namespace Colorful.RemoteObject
namespace Colorful.RemoteObject12


 {
{13
 public class ClientIPServerSinkProvider : IServerChannelSinkProvider
    public class ClientIPServerSinkProvider : IServerChannelSinkProvider14

 
     {
{15

16
 private IServerChannelSinkProvider next = null;
        private IServerChannelSinkProvider next = null;17

18
 public ClientIPServerSinkProvider()
        public ClientIPServerSinkProvider()19

 
         {
{20
 }
        }21

22
 public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData)
        public ClientIPServerSinkProvider(IDictionary properties, ICollection providerData)23

 
         {
{24
 }
        }25

26
 public void GetChannelData(IChannelDataStore channelData)
        public void GetChannelData(IChannelDataStore channelData)27

 
         {
{28
 }
        }29

30
 public IServerChannelSink CreateSink(IChannelReceiver channel)
        public IServerChannelSink CreateSink(IChannelReceiver channel)31

 
         {
{32
 IServerChannelSink nextSink = null;
            IServerChannelSink nextSink = null;33

34
 if (next != null)
            if (next != null)35

 
             {
{36
 nextSink = next.CreateSink(channel);
                nextSink = next.CreateSink(channel);37
 }
            }38

39
 return new ClientIPServerSink(nextSink);
            return new ClientIPServerSink(nextSink);40
 }
        }41

42

43

44
 public IServerChannelSinkProvider Next
        public IServerChannelSinkProvider Next45

 
         {
{46

 get
            get  { return next; }
{ return next; }47

 set
            set  { next = value; }
{ next = value; }48
 }
        }49
 }
    }50

51
 public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase
    public class ClientIPServerSink : BaseChannelObjectWithProperties, IServerChannelSink, IChannelSinkBase52

 
     {
{53
 private IServerChannelSink _next;
        private IServerChannelSink _next;54

55
 public ClientIPServerSink(IServerChannelSink next)
        public ClientIPServerSink(IServerChannelSink next)56

 
         {
{57
 _next = next;
            _next = next;58
 }
        }59

60
 public void AsyncProcessResponse(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers, System.IO.Stream stream)
        public void AsyncProcessResponse(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers, System.IO.Stream stream)61

 
         {
{62
 }
        }63

64
 public Stream GetResponseStream(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers)
        public Stream GetResponseStream(System.Runtime.Remoting.Channels.IServerResponseChannelSinkStack sinkStack, System.Object state, System.Runtime.Remoting.Messaging.IMessage msg, System.Runtime.Remoting.Channels.ITransportHeaders headers)65

 
         {
{66
 return null;
            return null;67
 }
        }68

69
 public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, out System.Runtime.Remoting.Messaging.IMessage responseMsg, out System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
        public System.Runtime.Remoting.Channels.ServerProcessing ProcessMessage(System.Runtime.Remoting.Channels.IServerChannelSinkStack sinkStack, System.Runtime.Remoting.Messaging.IMessage requestMsg, System.Runtime.Remoting.Channels.ITransportHeaders requestHeaders, System.IO.Stream requestStream, out System.Runtime.Remoting.Messaging.IMessage responseMsg, out System.Runtime.Remoting.Channels.ITransportHeaders responseHeaders, out System.IO.Stream responseStream)70

 
         {
{71
 if (_next != null)
            if (_next != null)72

 
             {
{73
 IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
                IPAddress ip = requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;74

75
 CallContext.SetData("IP", ip);
                CallContext.SetData("IP", ip);76

77
 ServerProcessing spres = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
                ServerProcessing spres = _next.ProcessMessage(sinkStack, requestMsg, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);78

79
 return spres;
                return spres;80
 }
            }81
 else
            else82

 
             {
{83
 responseMsg = null;
                responseMsg = null;84

85
 responseHeaders = null;
                responseHeaders = null;86

87
 responseStream = null;
                responseStream = null;88

89
 return new ServerProcessing();
                return new ServerProcessing();90
 }
            }91
 }
        }92

93

94

95
 public IServerChannelSink NextChannelSink
        public IServerChannelSink NextChannelSink96

 
         {
{97

 get
            get  { return _next; }
{ return _next; }98

 set
            set  { _next = value; }
{ _next = value; }99
 }
        }100
 }
    }101
 }
}102



1
 class Program
class Program2

 
     {
{3
 static void Main(string[] args)
        static void Main(string[] args)4

 
         {
{5
 int TcpPort = ConfigInfo.RemoteSocketPort;
            int TcpPort = ConfigInfo.RemoteSocketPort;6
 BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();
            BinaryServerFormatterSinkProvider provider = new BinaryServerFormatterSinkProvider();7
 provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
            provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;8
 //实例化自定义的Server Channel Sink类
            //实例化自定义的Server Channel Sink类9
 Colorful.RemoteObject.ClientIPServerSinkProvider IpInjProvider = new Colorful.RemoteObject.ClientIPServerSinkProvider();
            Colorful.RemoteObject.ClientIPServerSinkProvider IpInjProvider = new Colorful.RemoteObject.ClientIPServerSinkProvider();10
 provider.Next = IpInjProvider;//加入接收链
            provider.Next = IpInjProvider;//加入接收链11
 
            12
 IDictionary props = new Hashtable();
            IDictionary props = new Hashtable();13
 props["port"] = TcpPort;
            props["port"] = TcpPort;14
 
            15
 TcpChannel chan1 = new TcpChannel(props,null,provider);
            TcpChannel chan1 = new TcpChannel(props,null,provider);16

17
 ChannelServices.RegisterChannel(chan1, false);
            ChannelServices.RegisterChannel(chan1, false);18

19
 LifetimeServices.LeaseTime = TimeSpan.Zero;//租用周期
            LifetimeServices.LeaseTime = TimeSpan.Zero;//租用周期20
 RemotingConfiguration.RegisterWellKnownServiceType
            RemotingConfiguration.RegisterWellKnownServiceType21
 (
                (22
 typeof(Colorful.RemoteObject.Server),
                typeof(Colorful.RemoteObject.Server),23
 ConfigInfo.RemoteSocketURI,
                ConfigInfo.RemoteSocketURI,24
 WellKnownObjectMode.Singleton
                WellKnownObjectMode.Singleton25
 );
                );26
 Console.WriteLine(DateTime.Now.ToString() + "服务通道注册成功!等待数据服务请求
            Console.WriteLine(DateTime.Now.ToString() + "服务通道注册成功!等待数据服务请求
 ");
");            27

28
 Console.ReadLine();
            Console.ReadLine();29
 }
        }30
 }
    }
 验证客服端的合法性#region 验证客服端的合法性
 验证客服端的合法性#region 验证客服端的合法性
 /**//// <summary>
        /**//// <summary> /// 检查Remoting客户端的合法性
        /// 检查Remoting客户端的合法性 /// </summary>
        /// </summary> /// <returns></returns>
        /// <returns></returns> public bool CheckRemotingClient()
        public bool CheckRemotingClient()
 
         {
{ IPAddress data = (IPAddress)CallContext.GetData("ClientIPAddress");
            IPAddress data = (IPAddress)CallContext.GetData("ClientIPAddress");
 if (clientIPAddress.ContainsKey(data))
            if (clientIPAddress.ContainsKey(data))
 
             {
{ string msg = "接受远程地址:" + data.ToString() + "的服务请求";
                string msg = "接受远程地址:" + data.ToString() + "的服务请求"; Console.WriteLine(msg);
                Console.WriteLine(msg); return true;
                return true; }
            } else
            else
 
             {
{ string msg = "远程地址:" + data.ToString() +"不在许可范围内,服务请求被拒绝";
                string msg = "远程地址:" + data.ToString() +"不在许可范围内,服务请求被拒绝"; Console.WriteLine(msg);
                Console.WriteLine(msg); SQL2005DAL.CommDAL.WriteLogFile("RemotingClientTrace", msg, "Warring", false);
                SQL2005DAL.CommDAL.WriteLogFile("RemotingClientTrace", msg, "Warring", false); return false;
                return false; }
            }
 }
        } #endregion
        #endregion 
                    
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号