在iPhone上使用HTTP摘要身份验证

在iPhone上使用HTTP摘要身份验证,iphone,authentication,session-management,http-digest,Iphone,Authentication,Session Management,Http Digest,我有一个应用程序可以与使用HTTP摘要身份验证的服务器通信 在我看来,iPhone中的“会话”管理对于美国开发者来说是一个相当“黑盒子”。我们真的看不到框架如何处理/持久化http会话吗 如果我只是有点糊涂,有人能解释一下如何在iPhone上处理HTTP摘要身份验证吗 我的基本演练是: 向安全url发出请求 服务器发送一个401 客户端创建并持久化凭据,并将其传递回服务器 服务器验证凭证,若已验证则完成请求,若未验证则发送另一个401 对安全url进行后续请求 服务器再次请求授权 这适用于单

我有一个应用程序可以与使用HTTP摘要身份验证的服务器通信

在我看来,iPhone中的“会话”管理对于美国开发者来说是一个相当“黑盒子”。我们真的看不到框架如何处理/持久化http会话吗

如果我只是有点糊涂,有人能解释一下如何在iPhone上处理HTTP摘要身份验证吗

我的基本演练是:

  • 向安全url发出请求
  • 服务器发送一个401
  • 客户端创建并持久化凭据,并将其传递回服务器
  • 服务器验证凭证,若已验证则完成请求,若未验证则发送另一个401
  • 对安全url进行后续请求
  • 服务器再次请求授权
这适用于单个请求,但如果我提出其他后续请求,服务器会再次请求授权。服务器为特定用户保留了一个会话,但由于某种原因,iPhone没有在同一会话中发出请求。。。因此,每次客户端请求安全url时,服务器都必须抛出身份验证对象并创建一个新的身份验证对象

我肯定这是不正确的行为

如果我们看看浏览器在这种情况下的行为:

  • 浏览器从安全url请求数据
  • 服务器发送401
  • 浏览器提示用户输入凭证,保存凭证,并将凭证传递给服务器
  • 服务器验证凭证,若已验证则返回数据,若未验证则发送另一个401
  • 对安全URL的后续请求不会提示提供凭据,因为浏览器管理会话
我正在创建NSURLCredential并将其保存在nsurlCredentialStorage中。 然后,当应用程序收到“didReceiveAuthenticationChallenge”时,我从存储器中检索凭证并将其传递回,如果凭证不存在,则创建凭证(在第一次请求时)

任何帮助都将不胜感激。
谢谢。

我已经编写了一个带有HTTP身份验证的iPhone应用程序,并体验了您所描述的。(我的应用程序使用基本身份验证而不是摘要身份验证,但这并没有太大区别。)

问题的原因在iPhone方面。如果iPhone没有在HTTP请求头中发送凭据,服务器需要用401进行应答。事实上,即使凭证存储在凭证存储器中后,也很容易实现

这种奇怪的行为严重影响了应用程序的速度,因为每个请求都会导致两次服务器往返,而不是一次(第一次为401,第二次为200)

我已通过在HTTP请求头中手动设置凭据解决了此问题:

NSString* credentials = [NSString stringWithFormat: @"%@:%@", usr, pwd];
const char* credentialsChars = [credentials cStringUsingEncoding: NSUTF8StringEncoding];
credentials = [CommunicationUtil stringBase64WithData: (const UInt8*) credentialsChars length: strlen(credentialsChars)];
NSString* authorizationHeader = [NSString stringWithFormat: @"Basic %@", credentials];

NSMutableURLRequest* request =
    [[NSMutableURLRequest alloc] initWithURL: url 
        cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
        timeoutInterval: 15];

    [request setValue: authorizationHeader forHTTPHeaderField: @"Authorization"];
现在我的应用程序运行非常顺利,响应速度非常快


对于摘要身份验证,解决方案看起来略有不同。但是你会明白的。

第一件事是忘记HTTP会话,因为它们不会与摘要身份验证活动登录交互(有一种会话信息功能,但它是不同的)

事实上,使用摘要的主要原因之一是不必使用会话来维护登录状态。会话很繁重,会影响可伸缩性

我不能确定你的问题是什么,但我知道我首先要检查的是什么,那就是正确使用过时的和正确创建nonce

如果要求用户代理处理相同的临时事件,则用户代理只能处理身份验证而无需重新询问用户,或者在另一种情况下,我将在后面介绍(按此顺序更容易解释)

如果在每个请求中使用相同的nonce,那么用户代理将继续使用它以及来自用户/pass的“ha1”来请求后续资源。这是预先做的,所以挑战永远不会发生

当然,使用相同的nonce会带来不安全因素,因为重播攻击对于任何能够嗅探流量的人来说都是微不足道的。nonce必须定期更改

因此,如果您收到来自用户代理的具有无效授权头的请求,但其无效的原因是nonce错误(它使用的是过期的),那么在您的质询中包括“stale=true”(默认为false)。这会通知用户代理,您拒绝的原因是nonce已过时(当然,其他信息也可能是错误的,但这并不重要,因为您不会让它以任何方式播放)

在收到这样一个stale=true时,用户代理将知道它未被授权,但不是重新询问用户(如果它是无UI组件,则引发异常),而是使用新的nonce重试旧条件


我不知道这是否影响了您,但确定非当前状态和过时状态并发出信号的方式肯定是我首先考虑的问题。

摘要身份验证将看起来非常不同。如果ASIHTTPRequest已经支持它,我会使用它,而不是伪造一些密码。根据文档,ASIHTTPRequest支持,所以我同意tc的建议。我已经研究了摘要认证的细节,我不得不同意:我的实现相当麻烦。计算MD5哈希是最简单的部分。处理HTTP头中的所有细节是困难的部分。所以,是的:也许最好尝试一下ASIHTTPRequest。Jasarien,我是否认为这意味着这会让你走上正轨?(出于我的好奇心,或许还有其他人发现同样问题的好处)。