ChinaDHF
学而不思则罔,思而不学则殆。
posts - 41,  comments - 211,  trackbacks - 4

    在安全性要求不是很高的ASP.Net程序中,基于Forms的身份验证是经常使用的一种方式,而如果需要对WebService进行身份验证,最常用的可能是基于Soap 标头的自定义身份验证方式。如果对两者做一下比较的话,显然,基于Forms的验证方式更加方便易用,能否将Forms验证方式应用到WebService中去呢? 
    从理论上讲,使用基于Forms的方式对WebService进行身份验证是可行的,但是使用过程中会存在以下两个问题:
1.基于Forms的验证方式同时也是基于Cookie的验证方式,在使用浏览器时,这个问题是不需要我们考虑的。但对于使用WebService的应用程序来说,默认是不能保存Cookie的,需要我们自己去做这个工作。
2.WebService既然是一个A2A(Application To Application)应用程序,使用Web表单进行身份验证显然不太合适,而且,这将不可避免的造成人机交互,使WebService的应用大打折扣。
  接下来,我们就分步解决这两个问题:
1.Cookie的保存问题
    WebService的客户端代理类有一个属性CookieContainer可用于设置或获取Cookie集合,保存Cookie的任务就交给他了:

System.Net.CookieContainer cookieContainer = new System.Net.CookieContainer();

MyService.WebService service 
= new App.MyService.WebService();
service.CookieContainer 
= cookieContainer;

2.我们不想使用Web表单进行身份验证,幸运的是,ASP.Net表单验证中的表单页(即Web.config文件中 forms 元素内的loginUrl)同样可以指定为WebService文件。
    我们创建一个专门用作身份验证的Web服务,暂且命名为Login.asmx,然后让 loginUrl 等于 “Login.asmx”,当然,还需要在Web.config文件中的 authorization 节中禁止匿名访问(否则我们可就白忙活了),完成配置后的Web.config文件如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    
<system.web>
       
<compilation debug="false" />
      
<authentication mode="Forms">
        
<forms name="MyService" loginUrl="Login.asmx"></forms>
      
</authentication>
      
<authorization >
        
<deny users="?"/>
      
</authorization>
    
</system.web>
</configuration>

    其实我们并不想在未通过身份验证时让浏览器转向到Login.asmx,对于使用WebService的客户程序来说,真正的实惠在于:可以匿名访问Login.asmx中的方法(当然我们也可以把Login.asmx放在单独的目录中,然后允许对该目录的匿名访问来达个这个目的,但我觉得还是用loginUrl更优雅一些)。
    接下来,我们为Login.asmx添加用于身份验证的WebMethod:

[WebMethod]
public bool Check(string userName,string password)
{
    
if (userName == "aaaaaa" && password == "123456")//添加验证逻辑
    {
        System.Web.Security.FormsAuthentication.SetAuthCookie(userName, 
false);
        
return true;
    }

    
else
    
{
        
return false;
    }

}

    最后一步工作就是:让客户程序中的WebService实例与Login实例共享CookieContainer。

class Sample
{
    System.Net.CookieContainer cookieContainer 
= new System.Net.CookieContainer();

    
public void Login()
    
{
        MyServiceLogin.Login login 
= new App.MyServiceLogin.Login();
        login.CookieContainer 
= cookieContainer;
        login.Check(
"aaaaaa""123456");                       
    }


    
public void ShowHelloWorld()
    
{
        MyService.WebService service 
= new App.MyService.WebService();
        service.CookieContainer 
= cookieContainer;

        Console.WriteLine(service.HelloWorld());
    }

}

    Login()以后再ShowHelloWorld(),你是否看到了我们熟悉的“Hello World”?Ok,就这么简单!
posted on 2006-10-08 11:18 东海风 阅读(3219) 评论(21)  编辑 收藏

FeedBack:
2006-10-08 11:21 | Dflying Chen      
good
  回复  引用  查看    
2006-10-08 11:39 | aspnetx      
good
  回复  引用  查看    
#3楼 [楼主]
2006-10-08 11:51 | 东海风      
@Dflying Chen
@aspnetx

谢谢!
  回复  引用  查看    
2006-10-08 13:41 | 我不是神      
一直考虑这方面的问题,看后豁然开朗!!!!
  回复  引用  查看    
2006-10-08 17:41 | 林肯公园      
最后一步工作就是:让客户程序中的WebService实例与Login实例共享CookieContainer。

login.CookieContainer = cookieContainer;

您的意思是说,这样做之后,客户端app与webservices可以共享cookie?
看这是赋值语句,好像是当向嘛,不大理解 -.- 见笑了
  回复  引用  查看    
2006-10-08 18:53 | aspnetx      
CookieContainer应该上可以序列化的吧
我做c#登陆网站并且检索网站信息的时候
是把CookieHeader保存然后再给CookieContainer
其实关键的就是这个了
不过以前记得序列化CookieContainer仍是无法保留服务器发送过来的cookie,而用CookieHeader就好使了.这个为什么现在也没想明白.
  回复  引用  查看    
#7楼 [楼主]
2006-10-08 20:35 | 东海风      
@林肯公园
WebService、Login是客户程序中的两个代理类,service、login分别是以上两个代理类的实例,将service、login的CookieContainer属性设置为CookieContainer类的同一个实例。

@aspnetx
呵呵,没试过。
  回复  引用  查看    
2006-10-09 00:15 | 嘻哈呵嘿      
nice..
  回复  引用  查看    
2006-10-09 08:35 | saicn [未注册用户]
非常不错。
  回复  引用    
2006-10-09 11:26 | zyg      
我试过没有成功,能不能把完整代码帖出来呢?
  回复  引用  查看    
#11楼 [楼主]
2006-10-10 08:35 | 东海风      
@zyg
能描述一下没有成功的原因吗?
  回复  引用  查看    
2006-10-11 19:31 | Kevin Cheng      
thanks lot
回去试试先哈哈
  回复  引用  查看    
2006-10-26 10:10 | fzzf[匿名] [未注册用户]
不知道搂住测试没?
我试过.代码正确,就是不写Cookie?不知道什么原因,还望楼主指点,谢谢!

  回复  引用    
#14楼 [楼主]
2006-10-26 18:34 | 东海风      
@fzzf[匿名]
代码已经过多次测试,没有问题啊。不知你指的是身份验证不能成功呢还是无法在本机找到cookie文件?

  回复  引用  查看    
2007-04-11 15:29 | simba [未注册用户]
够厉害的
  回复  引用    
2007-04-15 16:01 | sky [未注册用户]
以后会用得上
  回复  引用    
2007-04-19 13:49 | lenovo [未注册用户]

  回复  引用    
2007-04-24 11:40 | 王琳 [未注册用户]
非常不错,学习
  回复  引用    
2007-07-20 21:17 | wangdong [未注册用户]
是否将上述代码粘贴在login.cs中?我这里总是报错说找不到myservice??

邮箱wangdong135@hotmail.com


可否将完整代码发我邮箱?

谢谢
  回复  引用    
2008-06-27 17:40 | 赵俊      
我发现根本就执行不到
public bool Check(string userName,string password)
方法,点击调用以后页面直接转到Login.asmx里了,不知道哪里执行错了!
  回复  引用  查看    
2008-07-03 13:49 | 果然如此      
注意:System.Net.CookieContainer cookieContainer = new System.Net.CookieContainer();
为全局定义。@赵俊

  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
 
另存  打印
 
计数器:

阿里妈妈再掀疯狂采购风,网站广告位严重告急,急召天下站长


<2006年10月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

与我联系

常用链接

留言簿(2)

随笔档案(39)

收藏夹(12)

技术网站

阅读排行榜