[技术回顾系列]--如何考虑WebService的安全性[一]
安全性问题是当今的热点,不管是在那个领域。本篇谈论的WEB服务安全性包括:身份验证[基于WINDWOS的身份验证和基于SOAP标头的身份验证],授权,模拟,使用NET框架底层的安全机制。
基于WINDWOS的身份验证方式比较简单,在此不作讨论和ASP.NET应用一样的配置使用。
一:模拟
实际上在ASP。NETWEB服务中的代码是以ASPNET用户的身份而不是以登录用户的身份在执行。这个自己一测便知。但是在使用过程中有没有别的办法让我们的ASP。NET不以ASPNET身份而以其他的身份执行呢,如以用户登录的身份来执行?模拟可以解决这样的问题。很简单,只需要在配置文件件中加入<identity impersonate="true">节点便可以实现。在此想要介绍的是一种更灵活的模拟方式:动态模拟。何谓动态模拟呢?就是在执行某个操作时,使程序用管理员的身份(而不是被模拟的用户或ASPNET帐户)执行,但在完成该操作后(如写日志操作)又恢复到原来的安全上下文去继续执行其他操作。答案是当然可以。不过我们需要调用非托管LogonUser方法并向其传递所需帐户的用户名,密码和域信息以检索特定用户的帐户标志。
PS:此LogonUser方法不在。NET框架基类库中,而在非托管Advapi32.dll中,可以创建一个包装函数使用非托管函数,这样的包装函数是用DllImport特性标记的不含任何代码的静态方法。DllImport特性中包含了非托管函数的信息,此包装函数如下:
public class DLLWrap
{
[DllImport("c:\\WINDOWS\\System32\\advapi32.dll")]
public static extern bool LogonUser(string userName,string domain,
string pwd,int logonType,int logonProvider,out int token);
[DllImport("c:\\WINDOWS\\System32\\Kernel32.dll")]
public static extern int GetLastError();
}
下面以一个WEB方法实现动态摸比的全部过程
[WebMethod]
pubic string GetUser()
{
string msg="user:"+User.Identity.Name;
int token;//待模拟的管理员用户标志
bool loggedOn;
//获得超级用户的标志
loggedOn=DLLWrap.LogonUse("administrator","domainName","123456",3,0,out token);
int ret=DLLWrap.GetLastError();//错误响应
if(ret!=0)
return "动态模拟"+WindowsIdentity.GetCurrent().Name+"错误";
IntPtr hToken=new IntPtr(token);//生成。NET平台下的句柄
//生成要模拟的用户对象
WindowsIdentity impersonnate=new WindowsIdentity (hToken);
创建WindowsImpersonationContext 类的一个新实例
WindowsImpersonationContext myImpersonate;
//模拟,将以超级用户的身份运行程序
myImpersonate=impersonnate.Impersonate();
//假如运行本程序需要用户有写的权限
FileStream fs=new FileStream("C:\\log.txt",FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter st=new StreamWriter(fs);
st.WriteLine("***"+DateTime.Now.Tostring()+"*****");
st.WriteLine("user:"+User.Identity.Name);
st.Close();
fs.Close();
//恢复到原来的身份
myImersonate.Undo();
string str="用户是否经过验证?"+User.Identity.IsAuthenticated;
str+=str+"用户名"+User.Identity.Name;
return str;
}
从上面的DEMO可以看出,通过调用非托管函数创建Windows用户标志还是很麻烦的事情,呵呵。不过最常用的可能是动态的起用对以验证了身份的用户的模拟。在这样的情况下,WEB服务以ASPNET用户身份,而在某些特殊时候,让WEB服务模拟当前用户。此时需要做的时启用窗体验证方式并禁止模拟。关闭配置文件的模拟
下面的DEMO动态模拟当前用户执行写C:\LOG.TXT文件的操作,在返回的字符串中带了执行WEB服务的进程的用户标志。
[WebMothod]
public string GetUser()
{
string msg="user:"+User.Identity.Name; //生成要模拟的用户对象
WindowsIdentity impersonnate=(WindowsIdentity).User.Identity;
创建WindowsImpersonationContext 类的一个新实例
WindowsImpersonationContext myImpersonate;
//模拟,将以超级用户的身份运行程序
myImpersonate=impersonnate.Impersonate();
//假如运行本程序需要用户有写的权限
FileStream fs=new FileStream("C:\\log.txt",FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter st=new StreamWriter(fs);
st.WriteLine("***"+DateTime.Now.Tostring()+"*****");
st.WriteLine("user:"+User.Identity.Name);
st.Close();
fs.Close();
//恢复到原来的身份
myImersonate.Undo();
string str="用户是否经过验证?"+User.Identity.IsAuthenticated;
str+=str+"用户名"+User.Identity.Name;
str+=str+"\n当前进程的运行身份:"+WindowsIdentity.GetCurrent().Name;
return str;
}
PS:运行条件:禁止匿名访问。启用IIS基本验证方式。
在客户端如何使用考虑了安全性的WEB服务呢
在考虑了安全性的情况下,用户代理需要向WEB服务提供凭证以验证其身份。
PS:如果是使用的集成WINDOWS验证,那么必须将Credentials属性设置为DefaultCredentials
Demo说明
localHost.Service1 service=new localHost.Service1();
CredentialCache credenCach=new CredentialCach();
//实例化一个NetWorkCredential 表示用户访问凭证
NetWorkCredential credenNet=new NetWorkCredential("adminisrtator","123456","domainName");
credenCach.add(new Uri(service.Url),"Base",credenNet);
service.Credentials=credenCach;
string ret=service.GetUser();
Console.WriteLine(ret);
下篇总结;基于SOAP标头的自定义解决方案。
基于WINDWOS的身份验证方式比较简单,在此不作讨论和ASP.NET应用一样的配置使用。
一:模拟
实际上在ASP。NETWEB服务中的代码是以ASPNET用户的身份而不是以登录用户的身份在执行。这个自己一测便知。但是在使用过程中有没有别的办法让我们的ASP。NET不以ASPNET身份而以其他的身份执行呢,如以用户登录的身份来执行?模拟可以解决这样的问题。很简单,只需要在配置文件件中加入<identity impersonate="true">节点便可以实现。在此想要介绍的是一种更灵活的模拟方式:动态模拟。何谓动态模拟呢?就是在执行某个操作时,使程序用管理员的身份(而不是被模拟的用户或ASPNET帐户)执行,但在完成该操作后(如写日志操作)又恢复到原来的安全上下文去继续执行其他操作。答案是当然可以。不过我们需要调用非托管LogonUser方法并向其传递所需帐户的用户名,密码和域信息以检索特定用户的帐户标志。
PS:此LogonUser方法不在。NET框架基类库中,而在非托管Advapi32.dll中,可以创建一个包装函数使用非托管函数,这样的包装函数是用DllImport特性标记的不含任何代码的静态方法。DllImport特性中包含了非托管函数的信息,此包装函数如下:
public class DLLWrap
{
[DllImport("c:\\WINDOWS\\System32\\advapi32.dll")]
public static extern bool LogonUser(string userName,string domain,
string pwd,int logonType,int logonProvider,out int token);
[DllImport("c:\\WINDOWS\\System32\\Kernel32.dll")]
public static extern int GetLastError();
}
下面以一个WEB方法实现动态摸比的全部过程
[WebMethod]
pubic string GetUser()
{
string msg="user:"+User.Identity.Name;
int token;//待模拟的管理员用户标志
bool loggedOn;
//获得超级用户的标志
loggedOn=DLLWrap.LogonUse("administrator","domainName","123456",3,0,out token);
int ret=DLLWrap.GetLastError();//错误响应
if(ret!=0)
return "动态模拟"+WindowsIdentity.GetCurrent().Name+"错误";
IntPtr hToken=new IntPtr(token);//生成。NET平台下的句柄
//生成要模拟的用户对象
WindowsIdentity impersonnate=new WindowsIdentity (hToken);
创建WindowsImpersonationContext 类的一个新实例
WindowsImpersonationContext myImpersonate;
//模拟,将以超级用户的身份运行程序
myImpersonate=impersonnate.Impersonate();
//假如运行本程序需要用户有写的权限
FileStream fs=new FileStream("C:\\log.txt",FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter st=new StreamWriter(fs);
st.WriteLine("***"+DateTime.Now.Tostring()+"*****");
st.WriteLine("user:"+User.Identity.Name);
st.Close();
fs.Close();
//恢复到原来的身份
myImersonate.Undo();
string str="用户是否经过验证?"+User.Identity.IsAuthenticated;
str+=str+"用户名"+User.Identity.Name;
return str;
}
从上面的DEMO可以看出,通过调用非托管函数创建Windows用户标志还是很麻烦的事情,呵呵。不过最常用的可能是动态的起用对以验证了身份的用户的模拟。在这样的情况下,WEB服务以ASPNET用户身份,而在某些特殊时候,让WEB服务模拟当前用户。此时需要做的时启用窗体验证方式并禁止模拟。关闭配置文件的模拟
下面的DEMO动态模拟当前用户执行写C:\LOG.TXT文件的操作,在返回的字符串中带了执行WEB服务的进程的用户标志。
[WebMothod]
public string GetUser()
{
string msg="user:"+User.Identity.Name; //生成要模拟的用户对象
WindowsIdentity impersonnate=(WindowsIdentity).User.Identity;
创建WindowsImpersonationContext 类的一个新实例
WindowsImpersonationContext myImpersonate;
//模拟,将以超级用户的身份运行程序
myImpersonate=impersonnate.Impersonate();
//假如运行本程序需要用户有写的权限
FileStream fs=new FileStream("C:\\log.txt",FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter st=new StreamWriter(fs);
st.WriteLine("***"+DateTime.Now.Tostring()+"*****");
st.WriteLine("user:"+User.Identity.Name);
st.Close();
fs.Close();
//恢复到原来的身份
myImersonate.Undo();
string str="用户是否经过验证?"+User.Identity.IsAuthenticated;
str+=str+"用户名"+User.Identity.Name;
str+=str+"\n当前进程的运行身份:"+WindowsIdentity.GetCurrent().Name;
return str;
}
PS:运行条件:禁止匿名访问。启用IIS基本验证方式。
在客户端如何使用考虑了安全性的WEB服务呢
在考虑了安全性的情况下,用户代理需要向WEB服务提供凭证以验证其身份。
PS:如果是使用的集成WINDOWS验证,那么必须将Credentials属性设置为DefaultCredentials
Demo说明
localHost.Service1 service=new localHost.Service1();
CredentialCache credenCach=new CredentialCach();
//实例化一个NetWorkCredential 表示用户访问凭证
NetWorkCredential credenNet=new NetWorkCredential("adminisrtator","123456","domainName");
credenCach.add(new Uri(service.Url),"Base",credenNet);
service.Credentials=credenCach;
string ret=service.GetUser();
Console.WriteLine(ret);
下篇总结;基于SOAP标头的自定义解决方案。