7

我有一个与使用 HTTP Digest 身份验证的服务器通信的应用程序。

在我看来,iPhone 中的“会话”管理对我们开发人员来说是相当“黑匣子”。我们真的看不到框架如何处理/持久化 http 会话吗?

如果我只是在这里昏暗,有人愿意解释如何在 iPhone 上处理 HTTP Digest 身份验证吗?

我的基本经历是:

  • 向安全 URL 发出请求
  • 服务器发送 401
  • 客户端创建并保存一个凭证,并将其传递回服务器
  • 服务器验证凭证,如果验证则完成请求,如果没有则发送另一个 401。
  • 发出后续请求以保护 url
  • 服务器再次请求授权......

这适用于单个请求,但如果我提出额外的后续请求,服务器会再次请求授权。服务器为特定用户保留了一个会话,但由于某种原因 iPhone 没有在同一个会话中发出请求......因此,服务器必须丢弃身份验证对象并在每次客户端时创建一个新对象向安全 URL 发出请求。

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

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

  • 浏览器从安全 url 请求数据
  • 服务器发送 401
  • 浏览器提示用户输入凭据,将其持久化,将其传递给服务器
  • 服务器验证凭据,如果验证则返回数据,否则发送另一个 401。
  • 由于浏览器管理会话,因此不会提示对安全 url 发出的后续请求提供凭据。

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

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

4

2 回答 2

3

首先,忘记 HTTP 会话,因为它们不与 Digest 身份验证活动登录交互(有一种会话信息功能,但有所不同)。

事实上,使用 Digest 的主要原因之一是不必为了保持登录状态而使用会话。会话很重,会损害可扩展性。

我不能确定你的问题是什么,但我确实知道我会首先检查什么,即正确使用陈旧和正确创建随机数。

如果用户代理被要求处理相同的随机数,或者在另一种情况下我稍后会谈到(按此顺序更容易解释),用户代理只能处理身份验证而不重新查询用户。

如果您在每个请求中使用了相同的随机数,那么用户代理将继续使用它以及来自用户/通行证的“ha1”来请求后续资源。这是先发制人的,所以挑战永远不会发生。

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

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

在接收到这样一个 stale=true 时,用户代理将知道它没有被授权,但是不会重新查询用户(或者如果它是一个无 UI 组件则抛出异常)将使用新的随机数重试旧条件。

我不知道这是否会影响您,但确定和发出信号的随机数和陈旧性的方式肯定是我首先要看的。

于 2010-08-18T11:05:56.447 回答
1

我编写了一个带有 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"];

现在我的应用程序运行非常顺利并且响应速度非常快。

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

于 2010-08-11T18:56:46.667 回答