CSharp Tips:应用程序访问集成Windows认证的站点

类别:.NET开发 点击:0 评论:0 推荐:
问题
从事过Web Application的人都知道,在一个Web Site可以允许用户匿名访问,也可以禁止匿名强制要求认证才能够访问。
在IIS的Directory Property/Directory Security下可以看到匿名访问(Anonymous access)和认证访问(Authenticated access)的选项。在认证访问中又有多种方式:基本认证(Basic)、摘要认证(Digest),还有著名的Windows集成(Integrated Windows authentication,以前应该叫做Challenge/Response)。
当选择和认证访问的时候,如果没有经过认证,任何请求都会被服务器拒绝,返回401-Unauthenticated的错误。通过IE访问Web Site,浏览器会帮你做掉很多事情,特别是当选择Windows集成模式,而用户又是登录域的,对用户感觉完全透明。但是在应用程序中怎么才能够向一个要求认证访问的站点发送请求呢?这就是我们的问题所在。
 
原因
在DotNet下面我们通常采用System.Web.HttpWebRequest/HttpWebResponse来完成有关HTTP的操作,对于客户端来说比较重要的就是发送请求的HttpWebRequest。
普通情况下,我们创建一个请求:
   oRequest = (System.Net.HttpWebRequest) WebRequest.Create(uri);
   if (oRequest != null)
   {
    // send request
    oRequest.ProtocolVersion = HttpVersion.Version11;
    oRequest.Method = @"GET";
    oResponse = (System.Net.HttpWebResponse) oRequest.GetResponse();
    }
这段代码请求允许匿名访问的站点的时候没有任何问题,但是当站点关闭匿名访问的开关的时候,就会收到上面提到的401的错误。因为我们并没有指定访问该站点的用户ID。
 
解决
HttpWebRequest类中有一个属性Credentials,该属性就是用来存放认证信息的。
如果希望用当前登录用户的认证信息,可以这么赋值:
     oRequest.Credentials = CredentialCache.DefaultCredentials;
CredentialCache.DefaultCredentials记录了应用程序当前运行上下文中的认证信息,但是你无法从中读取用户名、口令和登录域(都是空字符串),不过确确实实记录了当前登录用户的信息,这也是Windows的保护机制吧。
 
如果希望用一个指定用户的身份访问,那么就必须提供用户名,口令和域名:
     oCredential = new NetworkCredential(sUser,sPwd,sDomain);
     oRequest.Credentials = oCredential.GetCredential(new Uri(uri),String.Empty);
在GetCredential方法中可以指定认证方式,也就是“Basic”、“NTLM”之类。具体参数含义,参考MSDN。
完整的例子
   oRequest = (System.Net.HttpWebRequest) WebRequest.Create(uri);
   if (oRequest != null)
   {
    // send request
    oRequest.ProtocolVersion = HttpVersion.Version11;
    oRequest.Method = @"GET";
    if (sUser != String.Empty)
    {
     oCredential = new NetworkCredential(sUser,sPwd,sDomain);
     oRequest.Credentials = oCredential.GetCredential(new Uri(uri),String.Empty);
    }
    else
    {
     oRequest.Credentials = CredentialCache.DefaultCredentials;
    }
    oResponse = (System.Net.HttpWebResponse) oRequest.GetResponse();
    }
这样只要当前登录用户或者你提供帐号和口令的用户通过任何,你就可以像普通情况下一样访问Web Site上的资源了。当然如果提供了错误的用户名或者口令的话,不要来找我。
DotNet下非常简单,就到这里。
 
IE做了点什么?
题外话,谈谈当访问一个需要认证的站点的时候,IE做了点什么。
当服务端选择集成Windows的认证模式时,用户通过IE请求被保护的资源,服务端返回一个401的错误码,以及一个WWWW-Authenticate的HTTP报头(Header)。IE收到这个Header之后,将当前用户名、机器名和域名传递给服务端,服务端继续回应一个401的错误码以及WWW-Authenticate的报头。这是IE换算Password再次发送给服务端,这个时候认证才算完成。
如果当前登录Windows的用户没有权限访问服务端的资源,IE就会弹出一个对话框,要求用户输入访问用户名、口令和域名,再次重复上述过程。如果用户三次输入错误的信息,那么IE也玩不动了,直接告诉你“未经授权”。
可见IE还是做了很多事情的。如果我们要写一个比较好的客户端程序,也需要重复考虑这些问题。
 
 
参考文档
 
 
 

本文地址:http://com.8s8s.com/it/it45277.htm