在iPhone上使用HTTP摘要认证

7

我有一个应用程序,与使用HTTP摘要认证的服务器通信。

在iPhone中,“会话”管理对于我们开发人员来说似乎是黑盒子。我们无法看到框架如何处理/持久化http会话,这是否正确?

如果我在这里只是暗淡无光,请有人解释一下如何正确处理iPhone上的HTTP摘要认证?

我的基本步骤是:

  • 向受保护的url发出请求
  • 服务器发送401
  • 客户端创建和持续凭据,并将其传递回服务器
  • 服务器验证凭据,如果验证通过,则完成请求,如果未经验证,则发送另一个401。
  • 对安全url进行后续请求
  • 服务器再次请求授权........

它适用于单个请求,但是如果我进行其他后续请求,则服务器会再次请求授权。服务器已针对特定用户持久化了会话,但是由于某种原因,iPhone没有在同一会话中发出请求... 因此,服务器必须放弃身份验证对象并在每次客户端请求安全url时创建新对象。

我确定这不是正确的行为。

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

  • 浏览器从安全url请求数据
  • 服务器发送401
  • 浏览器提示用户凭据,持久化它并将其传递给服务器
  • 服务器验证凭据,如果验证通过,则返回数据,如果未经验证,则发送另一个401。
  • 对安全url进行后续请求不需要提示凭据,因为浏览器管理会话。

我正在创建NSURLCredential并在NSURLCrendtialStorage中持久化它。然后当应用程序收到“didReceiveAuthenticationChallenge”时,我从存储中检索凭据并将其返回,如果不存在,则创建凭据(在第一个请求上)。

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

2个回答

3
首先,要忘记HTTP会话,因为它们不与Digest身份验证活动登录交互(有一种会话信息能力,但它是不同的)。
实际上,使用Digest的主要原因之一是不必使用会话来维护已登录状态。会话很重,并且会影响可扩展性。
我不能确定您的问题是什么,但我知道我要首先检查的是正确使用过期和正确创建nonce。
如果用户代理被要求处理相同的nonce,或者在稍后的另一种情况下(更容易按照这个顺序解释),则只有在不重新查询用户的情况下才能处理身份验证。
如果您在每个请求中使用相同的nonce,则用户代理将继续使用它以及用户/密码的“ha1”来请求后续资源。这是预先完成的,因此挑战从未发生。
当然,使用相同的nonce引入了一定的不安全因素,因为可以窃听流量的任何人都可以轻松地进行重放攻击。 Nonce将不得不定期更改。
因此,如果您从用户代理收到具有无效授权标头的请求,但其无效的原因是nonce错误(它正在使用过期的nonce),则在您的挑战中包括“stale = true”(默认为false)。这通知用户代理您拒绝的原因是nonce已过期(当然,其他信息也可能错误,但无论如何您都不会让其播放)。
在收到这样的stale = true后,用户代理将知道它未经授权,但不会重新查询用户(或者如果它是无UI组件,则抛出异常),而是使用新的nonce重试旧标准。
我不能确定任何这些是否影响您,但nonce和陈旧性的确定和信号方式肯定是我要看的第一件事。

Jasarien,我是否可以理解你的勾选意味着这个答案对你有帮助?(出于我的好奇心,也许能够帮助其他遇到同样问题的人)。 - Jon Hanna

1

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

问题的原因在于iPhone端。如果iPhone没有在HTTP请求头中发送凭据,则服务器需要回答401。实际上,即使凭据存储在凭据存储中,iPhone也不会轻易地发送凭据。

这种奇怪的行为对应用程序的速度产生了严重影响,因为每个请求都会导致两次往返服务器而不是一次(第一次状态为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"];

现在我的应用程序运行非常流畅,响应速度也很快。

对于摘要认证,解决方案会略有不同。但是你会明白的。


1
摘要认证看起来会非常不同。如果ASIHTTPRequest已经支持它,我会使用它而不是弄一些加密。 - tc.
1
根据文档,ASIHTTPRequest可以实现,所以我会选择tc的建议。这样可以避免手动编写所有这些代码带来的很多麻烦。 - chilitechno.com
我已经学习了摘要认证的细节,不得不承认:它实现起来相当繁琐。计算MD5哈希值是最简单的部分,处理HTTP头中的所有细节是难点。所以,最好尝试使用ASIHTTPRequest。 - Codo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接