ChinaDHF
学而不思则罔,思而不学则殆。
posts - 41,  comments - 226,  trackbacks - 5

    在安全性要求不是很高的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 东海风 阅读(4172) 评论(27)  编辑 收藏 网摘

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();
为全局定义。@赵俊

  回复  引用  查看    
2008-08-12 11:13 | 王召冠      
service、login的CookieContainer属性设置为CookieContainer类的同一个实例。
===============================
我根本就没有找到代理类有什么 CookieContainer属性
大家讲解一个问题最好把实例源码公布,不要在那故作高深!

  回复  引用  查看    
2008-08-12 11:13 | 王召冠      
service、login的CookieContainer属性设置为CookieContainer类的同一个实例。
===============================
我根本就没有找到代理类有什么 CookieContainer属性
大家讲解一个问题最好把实例源码公布,不要在那故作高深!

  回复  引用  查看    
2008-08-29 16:46 | chuanyanyin[未注册用户]
我测试了一下,是成功的,但当我改变了service的url后,发现不成,但他们都是同一WebServer, 请问是何原因?
  回复  引用    
2008-10-31 17:22 | tellov[未注册用户]
我以前也这么做的,还行,不过我客户端每过19分钟就要去调用一下,不然等SESSION超时,就又要重新验证,最后小程序都用SOAP了,更方便
  回复  引用    
2008-12-19 13:25 | valu[未注册用户]
希望发源代码:valu@163.com
  回复  引用    
2009-05-07 14:31 | 李柏[未注册用户]
如果 设置了
<authentication mode="Forms">
<forms name="MyService" loginUrl="Login.asmx"></forms>
</authentication>
<authorization >
<deny users="?"/>
</authorization>

客户端添加Web引用时,只能引用Login.asmx里的方法,别的service都找不到了。

请问是如何实现
MyService.WebService service = new App.MyService.WebService();
service.CookieContainer = cookieContainer;

Console.WriteLine(service.HelloWorld());

我觉得 MyService.WebService 因为 不在Login.asmx,匿名情况都引用不到,还怎么实例化呢

  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 520975




相关文章:

相关链接:
计数器:

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


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

与我联系

搜索

 

常用链接

留言簿

随笔档案(39)

收藏夹(12)

技术网站

阅读排行榜