症状
<script type="text/javascript">loadTOCNode(1, 'symptoms');</script>如果 Internet Security and Acceleration (ISA) Server 2000 是链接到上游 Web 代理服务器, Web 浏览器中可能会收到完整 HTML 页和随机身份验证提示。
如果下游 ISAServer 计算机配置需要集成验证并且如果上游 Web 代理服务器也配置需要代理验证可能会发生这些症状。 此外, 下游 ISAServer 计算机上路由规则配置为向上游 Web 代理服务器提供基本验证凭据。
如果下游 ISAServer 计算机不配置为提供任何凭据或者被配置为向上游 Web 代理服务器提供集成验证凭据不会此行为不发生。
如果下游 ISAServer 计算机配置需要集成验证并且如果上游 Web 代理服务器也配置需要代理验证可能会发生这些症状。 此外, 下游 ISAServer 计算机上路由规则配置为向上游 Web 代理服务器提供基本验证凭据。
如果下游 ISAServer 计算机不配置为提供任何凭据或者被配置为向上游 Web 代理服务器提供集成验证凭据不会此行为不发生。
回到顶端
原因
<script type="text/javascript">loadTOCNode(1, 'cause');</script>在某些情况下, Web 浏览器可能尝试验证与下游 ISAServer 计算机已经被身份验证, 通过使用集成身份验证连接。 这可能导致下游 ISAServer 计算机将这些凭据传递给上游 Web 代理服务器。 因为凭据是不用于下游 ISAServer 计算机和上游 Web 代理服务器, 服务器返回需要 " 407 代理验证 " HTTP 响应。 下游 ISAServer 计算机然后将此 HTTP 响应回 Web 浏览器, 导致身份验证提示客户端计算机上。 因为客户端不能验证此请求, 会 Web 客户端浏览器上导致完整 HTML 页。
回到顶端
解决方案
<script type="text/javascript">loadTOCNode(1, 'resolution');</script>支持修补程序现已推出来自 Microsoft。 但是, 此修复程序用于更正本文中描述问题只。 只对遇到此特定问题的系统应用此修复程序。 此修复程序可能会收到其他测试。 因此, 如果您受此问题, 的影响不严重我们建议您等待下服务包包含此修复程序。
要解决此问题, 向 Microsoft 联机客户服务提交申请以获取此修复程序。 请以提交联机请求以获取此修复程序, 访问以下 MicrosoftWeb 站点:
如果当上游 Web 代理服务器没有任何访问控制 (使用匿名访问), 代替安装此修复程序, 然后运行您看到同一症状实现以下 MicrosoftKnowledgeBase 文章中介绍修复:
提示输入公司内网域的用户名和密码。我输入了自己的用户名和密码,正常添加引用。
在公司里面,网络访问都是通过ISA Server的(Microsoft® Internet Security and Acceleration Server),在使用Windows的时候不会出现任何问题,可是前两天装了Ubuntu Linux,遇到了些问题。
我使用firefox访问网络没有问题,只需要设好代理服务器地址,浏览网站时输入相应的用户名和密码即可,但在console下面使用apt-get更新系统时有问题。
开始我觉得应该这样设置代理:
export http_proxy=http://domaindomainuser:password@proxy.corpnet.com:8080
可是总会出现这个错误:
407 Proxy Authentication Required ( The ISA Server requires authorization to fulfill the request. Access to the Web Proxy service is denied. )
后来在网上搜索了一下,找到方法解决这个问题了:
Download ntlmaps-0.9.9.0.1 from here
$ tar -zxvf ntlmaps-0.9.9.0.1
$ vim ntlmaps-0.9.9.0.1/server.cfg
Edit PARENT_PROXY,PARENT_PROXY_PORT,USER,PASSWORD to match your preferences, then run main.py
$ ./ntlmaps-0.9.9.0.1/main.py &
$ export http_proxy=" http://127.0.0.1:5865"
$ sudo apt-get update
Now, everything is OK.
参考:
http://www.faqs.org/docs/Linux-H ... A-Server-HOWTO.html
http://www.ubuntuforums.org/showthread.php?t=20310
http://www.linuxquestions.org/questions/showthread.php?t=448387
http://kubuntuforums.net/forums/index.php?topic=7683.0
要解决此问题, 向 Microsoft 联机客户服务提交申请以获取此修复程序。 请以提交联机请求以获取此修复程序, 访问以下 MicrosoftWeb 站点:
http://go.microsoft.com/?linkid=6294451 (http://go.microsoft.com/?linkid=6294451)
注意 如果出现其他问题或解决任何是必需, 可能需要创建单独的服务请求。 通常支持成本将应用于其他支持问题以及执行不符合此特定修补程序问题。 请来创建单独的服务请求, 访问以下 MicrosoftWeb 站点: http://support.microsoft.com/contactus/?ws=support (http://support.microsoft.com/contactus/?ws=support)
警告 : 如果注册表编辑器使用不当, 可能会造成严重问题, 可能需要重新安装操作系统。 Microsoft 无法保证您能解决因注册表编辑器使用不当而导致问题。 需要您自担风险使用注册表编辑器。
以实现此修补程序, 中功能创建以下注册表值:
以实现此修补程序, 中功能创建以下注册表值:
1. | 停止 Web 代理服务。 |
2. | 启动注册表编辑器。 |
3. | 找到并单击以下注册表项: HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/W3Proxy/Parameters |
4. | 创建命名 RemoveRedundantProxyAuthorization 新 DWORD 值。 此新值赋予数据值为 1。 |
5. | 启动 Web 代理服务。 |
要恢复到原始配置, 请删除 RemoveRedundantProxyAuthorization 注册表值, 或将其数据值更改为 0 (零)。 在任一更改, 后重新启动 Web 代理服务。
// Create a new request to the mentioned URL.
WebRequest myWebRequest=WebRequest.Create("http://www.contoso.com");
WebProxy myProxy=new WebProxy();
// Obtain the Proxy Prperty of the Default browser.
myProxy=(WebProxy)myWebRequest.Proxy;
// Print myProxy address to the console.
Console.WriteLine("/nThe actual default Proxy settings are {0}",myProxy.Address);
try
{
Console.WriteLine("/nPlease enter the new Proxy Address to be set ");
Console.WriteLine("The format of the address should be http://proxyUriAddress:portaddress");
Console.WriteLine("Example:http://proxyadress.com:8080");
string proxyAddress;
proxyAddress =Console.ReadLine();
if(proxyAddress.Length==0)
{
myWebRequest.Proxy=myProxy;
}
else
{
Console.WriteLine("/nPlease enter the Credentials");
Console.WriteLine("Username:");
string username;
username =Console.ReadLine();
Console.WriteLine("/nPassword:");
string password;
password =Console.ReadLine();
// Create a new Uri object.
Uri newUri=new Uri(proxyAddress);
// Associate the new Uri object to the myProxy object.
myProxy.Address=newUri;
// Create a NetworkCredential object and is assign to the Credentials property of the Proxy object.
myProxy.Credentials=new NetworkCredential(username,password);
myWebRequest.Proxy=myProxy;
}
Console.WriteLine("/nThe Address of the new Proxy settings are {0}",myProxy.Address);
WebResponse myWebResponse=myWebRequest.GetResponse();
// Print the HTML contents of the page to the console.
Stream streamResponse=myWebResponse.GetResponseStream();
StreamReader streamRead = new StreamReader( streamResponse );
Char[] readBuff = new Char[256];
int count = streamRead.Read( readBuff, 0, 256 );
Console.WriteLine("/nThe contents of the Html pages are :");
while (count > 0)
{
String outputData = new String(readBuff, 0, count);
Console.Write(outputData);
count = streamRead.Read(readBuff, 0, 256);
}
// Close the Stream object.
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse Resource.
myWebResponse.Close();
Console.WriteLine("/nPress any key to continue.........");
Console.Read();
}
catch(UriFormatException e)
{
Console.WriteLine("/nUriFormatException is thrown.Message is {0}",e.Message);
Console.WriteLine("/nThe format of the myProxy address you entered is invalid");
Console.WriteLine("/nPress any key to continue.........");
Console.Read();
}
WebRequest myWebRequest=WebRequest.Create("http://www.contoso.com");
WebProxy myProxy=new WebProxy();
// Obtain the Proxy Prperty of the Default browser.
myProxy=(WebProxy)myWebRequest.Proxy;
// Print myProxy address to the console.
Console.WriteLine("/nThe actual default Proxy settings are {0}",myProxy.Address);
try
{
Console.WriteLine("/nPlease enter the new Proxy Address to be set ");
Console.WriteLine("The format of the address should be http://proxyUriAddress:portaddress");
Console.WriteLine("Example:http://proxyadress.com:8080");
string proxyAddress;
proxyAddress =Console.ReadLine();
if(proxyAddress.Length==0)
{
myWebRequest.Proxy=myProxy;
}
else
{
Console.WriteLine("/nPlease enter the Credentials");
Console.WriteLine("Username:");
string username;
username =Console.ReadLine();
Console.WriteLine("/nPassword:");
string password;
password =Console.ReadLine();
// Create a new Uri object.
Uri newUri=new Uri(proxyAddress);
// Associate the new Uri object to the myProxy object.
myProxy.Address=newUri;
// Create a NetworkCredential object and is assign to the Credentials property of the Proxy object.
myProxy.Credentials=new NetworkCredential(username,password);
myWebRequest.Proxy=myProxy;
}
Console.WriteLine("/nThe Address of the new Proxy settings are {0}",myProxy.Address);
WebResponse myWebResponse=myWebRequest.GetResponse();
// Print the HTML contents of the page to the console.
Stream streamResponse=myWebResponse.GetResponseStream();
StreamReader streamRead = new StreamReader( streamResponse );
Char[] readBuff = new Char[256];
int count = streamRead.Read( readBuff, 0, 256 );
Console.WriteLine("/nThe contents of the Html pages are :");
while (count > 0)
{
String outputData = new String(readBuff, 0, count);
Console.Write(outputData);
count = streamRead.Read(readBuff, 0, 256);
}
// Close the Stream object.
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse Resource.
myWebResponse.Close();
Console.WriteLine("/nPress any key to continue.........");
Console.Read();
}
catch(UriFormatException e)
{
Console.WriteLine("/nUriFormatException is thrown.Message is {0}",e.Message);
Console.WriteLine("/nThe format of the myProxy address you entered is invalid");
Console.WriteLine("/nPress any key to continue.........");
Console.Read();
}
**********************************
That cast is wrong. HttpWebRequest.Proxy is of type IWebProxy. There's
no guarantee that the class implementing this Interface is really a
WebProxy object.
There's really no point in reading the default proxy from the
HttpWebRequest if you want to use another one. Simply create a new
WebProxy object with the desired proxy URL, set the required
credentials and assign this object to the HttpWebRequest's Proxy
property.
*********************************
no guarantee that the class implementing this Interface is really a
WebProxy object.
There's really no point in reading the default proxy from the
HttpWebRequest if you want to use another one. Simply create a new
WebProxy object with the desired proxy URL, set the required
credentials and assign this object to the HttpWebRequest's Proxy
property.
*********************************
如果当上游 Web 代理服务器没有任何访问控制 (使用匿名访问), 代替安装此修复程序, 然后运行您看到同一症状实现以下 MicrosoftKnowledgeBase 文章中介绍修复:
317822 (http://support.microsoft.com/kb/317822/EN-US/) FIX: 问题浏览如果 ISA Server 2000 是链接到上游 Web 代理服务器
具体情况如下:
在外网的服务器上部署了一个Web Service,由于公司网络原因,仅能通过内网穿过代理服务器来访问外网的Web Service。在添加外网的Web Service时,出现了提示窗口,如下图:
提示输入公司内网域的用户名和密码。我输入了自己的用户名和密码,正常添加引用。
然后在调用时出现了问题,报错信息为:
请求因 HTTP 状态 407 失败 :Proxy Authentication Required ( The ISA Server requires authorization to fulfill the request. Access to the Web Proxy service is denied. ) 。
需要代理服务器认证,上网查了好多的帖子,发现给出的解决方案有误,原内容为:
首先引用 命名空间
using System.Net;
定义一个代理类
WebProxy myProxy = new WebProxy("192.168.0.3:8080",true);
然后又定义了一个用于身份验证的类
myService.Credentials = new NetworkCredential("username","password","domainname");
其中的myService变量为一个实例化的Web Service对象。
个人理解其实这是不对的,这个Credentials在注释中为“获取或设置XML Web services 客户端身份验证的安全凭据”。我们要设置的应该是通过代理时我们使用的安全凭据,所以这个设置是不对的。在上面定义的myProxy代理对象中,也有一个Credentials属性,它才是真正的“获取或设置提交给代理服务器进行身份验证的凭据”。所以我们将代码作如下修改:
设置代理对象的 Credentials 属性
myProxy.Credentials = new NetworkCredential("username "," password "," domainname ");
然后将定义的代理对象赋给Web Service对象的Proxy代理属性即可
myService.Proxy = myProxy;
作完这些设置就可以调用Web Service提供的接口了。
测试访问代理成功。
Update via ISA
在公司里面,网络访问都是通过ISA Server的(Microsoft® Internet Security and Acceleration Server),在使用Windows的时候不会出现任何问题,可是前两天装了Ubuntu Linux,遇到了些问题。
我使用firefox访问网络没有问题,只需要设好代理服务器地址,浏览网站时输入相应的用户名和密码即可,但在console下面使用apt-get更新系统时有问题。
开始我觉得应该这样设置代理:
export http_proxy=http://domaindomainuser:password@proxy.corpnet.com:8080
可是总会出现这个错误:
407 Proxy Authentication Required ( The ISA Server requires authorization to fulfill the request. Access to the Web Proxy service is denied. )
后来在网上搜索了一下,找到方法解决这个问题了:
Download ntlmaps-0.9.9.0.1 from here
$ tar -zxvf ntlmaps-0.9.9.0.1
$ vim ntlmaps-0.9.9.0.1/server.cfg
Edit PARENT_PROXY,PARENT_PROXY_PORT,USER,PASSWORD to match your preferences, then run main.py
$ ./ntlmaps-0.9.9.0.1/main.py &
$ export http_proxy=" http://127.0.0.1:5865"
$ sudo apt-get update
Now, everything is OK.
参考:
http://www.faqs.org/docs/Linux-H ... A-Server-HOWTO.html
http://www.ubuntuforums.org/showthread.php?t=20310
http://www.linuxquestions.org/questions/showthread.php?t=448387
http://kubuntuforums.net/forums/index.php?topic=7683.0
SIP协议中的认证方式 | |
作者:未知 , 来源:未知 , 点击:122 | |
注:请参照RFC3261使用HTTP认证SIP为认证系统提供了一个无状态的,试错机制,这个认证机制式基于HTTP的认证机制的。任何时候proxy服务器或者UA接收到一个请求(22.1节例外),它尝试检查请求发起者提供的身份确认。当发起方身份确认了,请求的接受方应当确认这个用户是否式通过认证的。在本文档中,没有建议或者讨论认证系统。 本节描述的“Digest”认证机制,只提供了消息认证和复查保护,没有提供消息完整性或者机密性的保证。上述的保护级别和基于这些Digest提供的保护,可以防止SIP攻击者改变SIP请求和应答。 注意由于这个脆弱的安全性,我们不赞成”Basic”(基本的)认证方法。服务器必须不能接收验证方法式”Basic”类型的信任书,并且服务器必须拒绝”Basic”。这是和RFC2543的改变。 框架SIP认证的框架和HTTP非常接近(RFC2617[17])。特别式,auth-scheme的BNF范式,auth-param,challenge,realm,realm-value,以及信任书都是一样的(虽然对”Basic”认证方案是不允许的)。在SIP,UAS使用401(Unauthorized)应答来拒绝UAC的身份(或者讲是考验UAC的身份,如果不通过,就是401)。另外,注册服务器,转发服务器可以使用401(Unauthorized)来应答身份认证,但是proxy必须不能用401,只能用407(Proxy Authentication Required)应答。对于Proxy-Authenticate的包含要求,Proxy-Authroization,WWW-Authenticate,Authorization在不同的消息中是相同的,如同在RFC2617[17]中讲述的一样。 由于SIP并没有一个规范的root URL的概念,所以,需要保护的空间的概念在SIP中的解释也不一样。realm字串单独定义被保护的区域。这个是和RFC2543的改变,在2543中Request-URI和realm一起定义了被保护的区域。 这个先前定义的被保护的区域回导致一定程度的混乱,因为Request-URI是UAC发送的,并且接收到Request-URI的认证服务器可能是不同的,并且真正的最终的Request-URI的格式可能对UAC并不知道。同样,早先的定义依赖于一个Request-URI中的SIP URI,并且看起来不允许其他的URI 方案(比如tel URL) 需要鉴别接收到的请求的UA使用者或者proxy服务器,必须根据下边的指导来为他们的服务器创建一个realm字串。 o Realm字串必须是全局唯一的。我们强调这个realm字串必须包含一个主机名或者域名,遵循3.2.1节或者RFC2617[17]的推荐 o Realm字串应当是一个可读的能够展示给用户的字串。 例如: INVITE sip:bob@biloxi.com SIP/2.0 Authorization: Digest realm=”biloxi.com”,<…> 通常,SIP认证对于特定realm(一个保护区域)是有意义的。因此,对于Digest认证来说,每一个类似的保护区域都有自己的用户名和密码集合。如果服务器对特定请求没有要求认证,那么它可以接收缺省的用户名,”anonymous”,并且这个用户名没有密码(密码是””)。类似的,代表多个用户的UAC,比如PSTN网关,可以有他们自己的设备相关的用户名和密码,而不是每一个用户名一个用户名密码(这就是说,比如网关,有一个网关的用户和密码,而不是说通过网关的每一个实际用户和密码)。 当服务器可以正确处理绝大部分SIP请求,有本文档约定了两类请求要求特别的认证处理:ACK和CANCEL。在某一个认证方案下,并且这个认证方案是使用应答来放置计算nonces(比如Digest),那么对于某些没有应答的情况,就会出现问题,比如ACK。所以,基于这个原因,一个服务器接受在INVITE请求中的信任书,也必须同样接收对应ACK的信任书。UAC通过赋值所有的INVITE请求中的Authorization和Proxy-Authorization头域值来创建一个相关的ACK消息。服务器必须接收这个ACK请求。 虽然CANCEL方法具有应答(2xx),服务器必须不能拒绝CANCEL请求,因为这些请求不能被重新提交。通常,如果CANCEL请求和被CANCEL的请求来自同一个节点(假设某种通讯协议,或者网络层有安全关系26.2.1节描述),服务器应当接收CANCEL请求。 当UAC接收到验证拒绝,并且UAC设备并不知道realm验证失败的具体原因,它必须展示给用户,验证失败的”realm”参数内容(既可以在WWW-Authenticate头域或者Proxy-Authenticate头域)。对于给自己的realm预先配置信任状的UA服务提供商来说,应当注意到这样一点:当被一个预先配置信任状的设备拒绝的时候,用户不会有机会在这个realm中展示他们自己的信任状。 最后,注意即使一个UAC能够定位与相关realm匹配的信任书,也有可能存在这个信任书可能不在有效,或者某个服务器会用什么原因不接受这个信任书(特别是当提供的是没有口令的”anonymous”用户时)。在这种情况下,服务器可能会继续拒绝,或者返回一个403 Forbidden。UAC必须不能再次使用刚才被拒绝的信任书进行尝试(如果当前环境没有改变,那么请求可以再次尝试)。 用户到用户的认证。当UAS收到一个UAC发起的请求,UAS在请求被处理之前进行身份认证。如果请求中没有信任书(在Authorization头域),UAS可以使用401(Unauthorized)拒绝认证,并且让客户端提供一个认证书。 WWW-Authenticate应答头域必须在401(Unauthorized)应答消息中出现。这个头域值包含了至少一个表明认证方式和适用realm的参数的拒绝原因。 在401中的WWW-Authenticate头域例子: WWW-Authenticate:Digest, realm=”biloxi.com”, qop=”auth,auth-int”, nonce=”dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41" 当原始请求的UAC接收到这个401(Unauthorized)应答的时候,如果可能的话,他应当重新组织这个请求,并且填写正确的信任书。在继续处理之前,UAC可以要求原始用户输入信任书。一旦信任书(不管是用户输入的,还是内部密钥)提供了,UA应当把这个给特定To头域和”realm”字段的信任书cache起来,以备给这个地址下一个请求时候使用。UA可以用任何方式来cache这个信任书。 如果没有找到对应realm的信任书,UAC应当尝试用用户”anonymous”和空口令来重新尝试这个请求。 一旦找到了一个信任书,那么UA应当要求在UAS或者注册服务器上认证自己,这是通常的情况,但是并非一定要求的,在接收到一个401(Unauthorized)应答后-可以在请求中增加一个Authorization头域然后再认证。Authorization头域包含了具有这个UA到请求的资源所在的realm(区域)的信任书和所需要的认证支持的参数和重现保护的参数。 Authorization头域例子: Authorization: Digest username=”bob”, realm=”biloxi.com”, nonce=”dcd98b7102dd2f0e8b11d0f600bfb0c093", uri=”sip:bob@biloxi.com”, qop=auth, nc=00000001, cnonce=”0a4f113b”, response=”6629fae49393a05397450978507c4ef1", opaque=”5ccc069c403ebaf9f0171e9517f40e41" 当UAC在接收到401(Unauthorized)或者407(ProxyAuthenticationRequired)应答之后,重新用它的信任书来提交请求,它必须增加Cseq头域的值,就像发送一个正常的新请求一样。 Proxy到用户的认证类似的,当UAC发送一个请求到proxy服务器,proxy服务器可以在处理请求之前,验证原始请求的认证。如果请求中没有信任书(在Proxy-Authorization头域),proxy可以用407(Proxy Authentication Required)拒绝这个原始请求,并且要求客户端提供适当的信任书。proxy必须在407(ProxyAuthenticationRequired)应答中增加一个Proxy-Authenticate头域,并且在这个头域中给出适用于本proxy的认证资源。 对于Proxy-Authenticate和Proxy-Authorization一起在[17]中描述,两者有一个不同。Proxy不能在Proxy-Authorization头域中增加值。所有的407(ProxyAuthenticationRequired)应答必须转发到上行队列,遵循发送应答的步骤发送到UAC。UAC负责在Proxy-Authorization头域值增加适用于这个proxy要求认证的这个proxy的realm的信任书。 如果proxy要求UAC在请求中增加Proxy-Authorization头域并且重新提交请求,那么UAC应当增加Cseq头域的值,就像一个新请求一样。不过,这样就导致提交原始请求的UAC需要忽略UAS的应答,因为Cseq的值可能是不一样的。 当原始请求的UAC接收到一个407(Proxy Authentication Required)的时候,如果可能,它应当使用正确的信任书重新组织请求。它应当和对前边讲述的401应答的处理步骤一样显示和处理”realm”参数。 如果没有找到对应realm的信任书,那么UAC应当尝试用用户”anonymous”和空口令重新尝试请求。 UAC也应当cache这个在重新发送请求中的信任书。 我们建议使用下列步骤来cache一个proxy的信任书: 如果UA在给特定Call-ID的请求的401/407应答中,接收到一个Proxy-Authenticate头域,它应当合并对这个realm的信任书,并且为以后具有相同Call-ID的请求发送这个信任书。这些信任书必须在对话中被cache住;不过如果UA配置的是它自己的本地外发proxy,那么如果出现要求认证的情况,那么UA应当cache住跨对话的信任书。注意,这个意味着在一个对话中的请求可以包含在Route头域中所经过proxy都不需要的信任书。 任何希望在proxy服务器上认证的UA――通常,但是并非必须,在接收到407(Proxy Authentication Required)应答之后――可以在请求中增加一个Proxy-Authorization头域然后再次尝试。Proxy-Authorization请求头域允许客户端像proxy来证明自己(或者使用者)的身份。Proxy-Authorization头域包含了UA提供给proxy和/或者请求资源所在的realm的身份认证信息的信任书。 一个Proxy-Authorization头域值只提供给指定proxy验证的,这个proxy的realm是在”realm”参数中指明的(这个proxy可以事先通过Proxy-Authenticat头域提出认证要求)。当多个proxy组成一个链路的时候,如果proxy的realm和请求中的Proxy-Authorization头域的”realm”参数不匹配,那么这个proxy就不能使用本Proxy-Authorization头域值来验证。 注意,如果一个认证机制不支持Proxy-Authorization头域的realm,porxy服务器必须尝试分析所有的Proxy-Authorization头域值来决定是否其中之一有这个proxy认为合适的信任书。因为这个方法在大型网络上很耗时间,proxy服务器应当使用一个一个支持Proxy-Authorization头域的realm的认证方案。 如果一个请求被分支(参见16.7节),可能对同一个UAC有不同的proxy服务器和/或者UA希望要求认证。在这种情况下,分支的proxy服务器有责任把这些被拒绝的认证合并成为一个应答。每一个分支请求的应答中接收到WWW-Authenticate和Proxy-Authenticate头域值必须由这个分支proxy放置在同一个应答中发送给UA;这些头域值的顺序并没有影响。 当proxy服务器给一个请求发出拒绝认证的应答,在UAC用正确的信任书重新发请求过来之前,不会转发这个请求。分支proxy可以同时向多个要求认证的proxy服务器转发请求。每一个proxy在没有接收到UAC在他们各自的realm的认证之前,都不会转发这个请求。如果UAC没有给这些失败的验证提供信任书,那些发出拒绝通过认证的proxy是不会把请求转发给UA的目标用户的,因此,分支的优点就少了很多。 当针对包含多个拒绝认证的401(Unauthorized)或者407(Proxy Authentication Required)应答重新提交请求时,UAC应当对每一个WWW-Authenticate和Proxy-Authorization头域值提供一个信任书。根据上边的说明,一个请求的多个认证书应当用”realm”参数分开。 不过,在同一个401(Unauthorized)或者407(Proxy Authentication Required)应答中,可能包含对同一个realm的多个验证拒绝。例如,当在相同域的多个proxy,使用共同的realm,接收到了一个分支请求,并且认证拒绝了的时候,就会有这样的情况。当UAC重新尝试这个请求的时候,UAC因此会提供多个Authorization或者Proxy-Authorization头域,包含相同的”realm”参数。并且对于同一个realm,应当有相同的信任书。 Digest 认证方案奔进诶描述了对HTTP Digest 认证方案的SIP修改和简化。SIP使用了和HTTP[17]几乎完全一样的方案。 由于RFC 2543是基于RFC2069[39]定义的HTTP Digest的,支持RFC2617的SIP服务器也必须确保他们和RFC2069兼容。RFC2617定义了保证兼容性的步骤。注意,SIP服务器必须不能接收或者发出Basic认证请求。 Digest认证的规则在[17]中定义,只是使用”SIP/2.0”替换” HTTP/1.1”,并且有如下的不同: 1、 URI有着如下的BNF: URI=SIP-URI/SIPS-URI 2、 在RFC 2617定义中,有一个HTTP Digest认证的Authorization头域”uri”参数的错误,是没有括号配对的错误。(在RFC2617的3.5节的例子是正确的)。对于SIP来说,’uri’参数必须在引号中引起来。 3、 digest-uri-value的BNF是: digest-uri-value=Request-URI; 在25节定义。 4、 对SIP来说,产生基于Etag的nonce的步骤例子不适用。 5、 对SIP来说,RFC2617[17]关于chache操作不适用。 6、 RFC2617[17]要求服务器检查请求行的URI,并且在Authorization头域的URI要指向相同的资源。在SIP中,这两个URI可以指向不同的用户,因为是同一个proxy转发的。因此,在SIP,一个服务器应当检查在Authorization头域值的Request-URI和服务器希望接收请求的用户是否一致,但是如果两者不一致,并无必要展示成为错误。 7、 在Digest认证方案中,关于计算消息完整性保证的A2值的一个澄清,实现着应当假定,当包体是空的(也就是说,当SIP消息没有包体)应当对包体的hash值产生一个M5hash空串,或者: H(entity-body)=MD5(“”)= "d41d8cd98f00b204e9800998ecf8427e" 8、 RFC2617指出了在Authorization(以及扩展的Proxy-Authorization)头域中,如果没有qop指示参数,就不能出现cnonce值。因此,任何基于cnonce(包括”MD5-Sess”)的运算都要求qop指数先发送。在RFC2617中的”qop”参数是可选的,这是为了向后兼容RFC2069;由于RFC2543是基于RFC2069的,”qop”参数必须被客户和服务器依旧是当作可选参数存在。不过,服务器必须始终在WWW-Authentication和Proxy-Authenticate头域值中传送”qop”参数。如果一个客户端在一个拒绝认证的应答中收到一个”qop”参数,他必须把这个”qop”参数放在后续的认证头域中。 |