用.Net Remoting做后台服务,十分方便,但是安全性也不能忽视,如果只在客户端进行身份验证,只要有经验的人都可以修改客户端,轻松绕过客户端的检验程序,直接调用服务端的服务,非常不安全。
.Net Remoting的安全性保证,大部分只提到部署在IIS上,降低了.Net Remoting的运行效率,另外也不能支持TCP的二进制传输(待商榷)。最佳方式,应该做成NT Service。此时该如何保证.Net Remoting的安全性呢?客户端调用服务端的一个方法,我们都希望能自动地将客户端的信息(类似Web开发的Session),我们暂且把这个信息叫着令牌(Token)。通过令牌,我们可以获得用户的Id。
如何在Remoting域(Domain)和客户端的Domain传递信息(无须显式地传递)?我们利用.Net Remoting的自动消息处理机制,通过Call Context来完成,即通过System.Runtime.Remoting.Messaging.CallContext类来实现。
第一步:将这些信息进行线程配置,配置到客户端的线程中
第二步:发生调用时,Remoting查找线程中保存的Call Context。
现在我们采用最简单的代码来表达:
----------------------------------------------------------------
公共部分:
[Serializable]
public class ContextToken:ILogicalThreadAffinative
{
private string _token = string.Empty;
public ContextToken( string token)
{
_token = token;
}
public string Token
{
get{return _token;}
set{_token = value;}
}
}
标记为Serializable,表示对象支持Serialize和De-Serialize;实现ILogicalThreadAffinative(一个不完整的接口,没有任何属性和方法),让对象支持从客户端线程中复制到服务端线程中。
-----------------------------------------------------------------
static HashTable _hs = new HashTable();
服务端:
public string LogIn( int userId, string psw )
{
//TODO 进行身份校验
string tokenString = Guid.NewGuid().ToString();
//保存
_hs[tokenString] = userId;
return tokenString;
}
public void SecurityFunction()
{
ContextToken token = CallContext.GetData().("PalSolt") as ContextToken;
if( token == null )
{
throw new Exception("不具有令牌");
}
int userId = (int)_hs[token.Token]
//TODO 根据userId来判断是否能调用此方法
//具体方法实现
}
------------------------------------------------------------------
客户端:
Main()
{
Service service = ...;//根据URL和端口来获得远程服务
string token = service.Login( 1, "hzpal");
//进行客户端线程配置
CallContext.SetData("PalSolt", new ContextToken(token) );
service.SecurityFunction();
}
----------------------------------------------------------------------------
小结:上面的只是一个示例,我们可以根据自己的需要来设计自己的权限验证模式。可以看出,我们无须显式地传递令牌,非常类似于Web的Session .
*以上代码直接在网页上编写,不能保证没有输入错误。采用此思路写的程序,在.Net Framework1.1下保证可以实现。
http://www.hzpal.com http://www.glassoo.com 派尔科技技术部
*此文无需经过同意,欢迎转载,不过务必保留上行的网址