二、 Windows集成验证
服务端IIS设置为不允许匿名访问,只选择winodws集成验证,客户端使用HttpWebRequest发送一个get请求,请求一个页面。
要请求需要windows集成验证的资源,前一篇文章已经讨论过,客户端必须选择NTLM或Kerberos这两种验证方式中的一种,传送客户端登录用户的用户凭据到服务端进行验证。
对于NTLM验证来说,客户端使用登录用户的密码派生的key加密服务端发来的质询码,服务端也对质询码做同样的加密处理,两端的加密结果一致,则表明验证通过。
对于Kerberos来说,客户端只发送登录用户的访问这个IIS的验证票,这个验证票只有这个用户和IIS服务器能识别,IIS只凭客户的验证票就可验证用户的身份。
HttpWebRequest的Credentials属性用来承载用户的用户凭据。
CredentialCache类的静态DefaultCredentials 属性能够获取运行当前代码的用户系统凭据。
DefaultCredentials 属性仅适用于基于 NTLM、协商和 Kerberos 的身份验证。
DefaultCredentials 表示运行应用程序的当前安全上下文的系统凭据。对于客户端应用程序,这些通常是运行应用程序的用户的 Windows 凭据(用户名、密码和域)。DefaultCredentials可以获得用于Kerberos验证的身份验证票,也可以获得用于NTLM验证的当前用户的用户名和密码。
为了在应用程序代码中加上对windows集成验证的支持,只需在上述匿名访问的代码中给HttpWebRequest对象的赋予用户系统凭据即可,HttpWebRequest对象会根据实际情况选择使用哪一种验证方式,并传送相应的用户凭据,在http请求发送出去之前增加以下代码:
myHttpWebRequest.Credentials = CredentialCache.DefaultCredentials;
Windows集成验证,HttpWebRequest对象选择哪种验证方式,基本会出现两种情况:
1、 客户端和服务端机器都在域,客户端以域帐户登录,以服务器名访问
1.1. 第一次HttpWebRequest先以匿名发送http请求
GET /iisstart.htm HTTP/1.1
Host: logs:81
Connection: Keep-Alive
1.2. 服务端返回无授权回应
HTTP/1.1 401 Unauthorized
Content-Length: 1327
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Fri, 23 Nov 2007 07:22:32 GMT
1.3. 再次请求,选择Kerberos验证,附带上此用户的验证票
HttpWebRequest首选到AD中查询要访问的服务器是否在域中,如果是在同一域中,则直接发送Kerberos验证的用户验证票。如果服务器不在域中,则会选择NTLM验证。
这里的情况是双方都在域中,选择Kerberos验证。
GET /iisstart.htm HTTP/1.1
Authorization: Negotiate YIIEzQYGKwYBBQUCoIIEwTCCBL2gJDAiBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKKwYBBAGCNwICCqKCBJMEggSPYIIEiwYJKoZIhvcSAQICAQBuggR6MIIEdqADAgEFoQMCAQ6iBwMFACAAAACjggOiYYIDnjCCA5qgAwIBBaEOGwxTWkJUSS5HT1YuQ06iFzAVoAMCAQKhDjAMGwRIVFRQGwRsb2dzo4IDaDCCA2SgAwIBF6EDAgEMooIDVgSCA
Host: logs:81
1.4. 服务端验证通过,返回页面
HTTP/1.1 200 OK
Content-Length: 167
Content-Type: text/html
Last-Modified: Wed, 14 Nov 2007 08:21:24 GMT
Accept-Ranges: bytes
ETag: "bf2d
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
WWW-Authenticate: Negotiate oYGgMIGdoAMKAQChCwYJKoZIgvcSAQICooGIBIGFYIGCBgkqhkiG9xIBAgICAG9zMHGgAwIBBaEDAgEPomUwY6ADAgEXolwEWgai3BchBA/s/Vtx44FMiv7n0LcpxmkRlVRhgIhsuijQnu6/qIb0AsMrIU4nHqDlZnLOkVwlXDAIiTumPWfHK+V/DmjKF5O6jlJVdFSu9xghGGyYivc3fvCWSQ==
Date: Fri, 23 Nov 2007 07:22:32 GMT
<html>
<head>
<meta HTTP-EQUIV="Content-Type" Content="text/html; charset=gb2312">
</head>
<body bgcolor=white>
This is a simple page!
</body>
</html>
2、 客户端和服务端机器都在域,客户端以域帐户登录,以服务器名访问以外的所有情况
2.1. 第一次HttpWebRequest先以匿名发送http请求
GET /iisstart.htm HTTP/1.1
Host: logs:81
Connection: Keep-Alive
2.2. 服务端返回无授权回应
HTTP/1.1 401 Unauthorized
Content-Length: 1327
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Fri, 23 Nov 2007 07:22:32 GMT
2.3. HttpWebRequest选择NTLM验证,请求质询码
HttpWebRequest判断不满足客户端以域账户登录,并且访问的服务器也是在域中,HttpWebRequest即选择NTLM。
GET /iisstart.htm HTTP/1.1
Authorization: Negotiate TlRMTVNTUAABAAAAt4II4gAAAAAAAAAAAAAAAAAAAAAFAs4OAAAADw==
Host: 192.168.100.5:81
2.4. 服务器返回质询码
HTTP/1.1 401 Unauthorized
Content-Length: 1251
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate TlRMTVNTUAACAAAACgAKADgAAAA1goniKBDxpIifbe0AAAAAAAAAAHwAfABCAAAABQLODgAAAA9TAFoAQgBUAEkAAgAKAFMAWgBCAFQASQABAAgATABPAEcAUwAEABgAcwB6AGIAdABpAC4AZwBvAHYALgBjAG4AAwAiAGwAbwBnAHMALgBzAHoAYgB0AGkALgBnAG8AdgAuAGMAbgAFABgAcwB6AGIAdABpAC4AZwBvAHYALgBjAG4AAAAAAA==
X-Powered-By: ASP.NET
Date: Fri, 23 Nov 2007 08:46:23 GMT
2.5. HttpWebRequest发送登录本机的账户加密后的质询码
HttpWebRequest通过CredentialCache.DefaultCredentials获得登录本机的用户名和口令,用口令派生的key加密质询码发送到服务器。
GET /iisstart.htm HTTP/1.1
Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAGYAAAAYABgAfgAAAAoACgBIAAAACgAKAFIAAAAKAAoAXAAAABAAEACWAAAANYKI4gUCzg4AAAAPUwBaAEIAVABJAGoAaQBuAGoAegBKAEkATgBKAFoA8Le58UfsaJIAAAAAAAAAAAAAAAAAAAAAsTIQTM1MCkPFXRkaNpjW+aLQCXsOGnUiDBp33pfcOMLLQJQuAyM/zQ==
Host: 192.168.100.5:81
2.6. 服务器通过验证,返回页面
HTTP/1.1 200 OK
Content-Length: 167
Content-Type: text/html
Last-Modified: Wed, 14 Nov 2007 08:21:24 GMT
Accept-Ranges: bytes
ETag: "bf2d
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Fri, 23 Nov 2007 08:46:23 GMT
<html>
<head>
<meta HTTP-EQUIV="Content-Type" Content="text/html; charset=gb2312">
</head>
<body bgcolor=white>
This is a simple page!
</body>
</html>
3、 客户端传送定制用户凭据到服务端
前两种情况都是传送客户端当前登录用户的用户凭据到服务端,但有时会需要客户端根据不同的情况以服务端的不同的用户帐号访问服务端资源。
HttpWebRequest.Credentials属性不设置为缺省登录本机的用户CredentialCache.DefaultCredentials,使用NetworkCredential提供定制的用户凭据,这样用法只能使用NTLM验证。
通过NetworkCredential对象定制一个用户凭据,像这样:
myHttpWebRequest.Credentials = new NetworkCredential("用户名", "口令");
这里的用户名用户名和口令是服务端的用户,这样设置以后,HttpWebRequest的行为跟上面第二种情况一样,也是先以匿名发送请求,收到服务端返回的无授权(要求windows验证)的http回应后,HttpWebRequest选择NTLM,其后的过程也跟上面第二种情况一样。