NSURLCredentialPersistencePermanent 似乎不是永久的?

发布于 2024-11-19 00:08:56 字数 3874 浏览 2 评论 0原文

我已经尝试解决这个问题有一段时间了,但没有成功。诸如这里的问题之类的问题或关于使用身份验证的问题苹果和其他博客 提供了一些线索,但是不是全部。

我想解决的基本问题如下:

我通过利用 NSURLConnection 的委托以及带有 NSURLProtectionSpace 和 NSURLCredentialStorage 的 NSURLCredential 成功地对我的服务器进行了身份验证。然而,即使我将 NSURLCredential 的持久性设置为 NSURLCredentialPersistencePermanent,在第一次提供我的凭据后,我会随机从服务器收到身份验证质询(401,然后是 200) - 难道不是这样吗,因为 NSURLCredentialPersistencePermanent 会永久持续?随机的事情就是没有意义的事情。

有时它可以工作,并且对服务器的后续调用可以正常返回 200。然后又不行,并且返回 401 和 200。 Mike Abdullah 在此处很好地描述了该过程。所以我的第一个猜测是,返回 401 身份验证并获得 200 的过程是标准程序,无法消除。然而有时我可以消除401。所以我似乎错过了一些东西。

我发送的请求是一些 GET 和两个 POST。问题是一个 POST 正在上传大量数据。当收到 401 时,数据仍然会在身份验证后上传到 nirvana,然后再次上传。

我的后备解决方案是在收到 401 时阻止数据发送。我现在正在研究这个问题,这似乎很棘手,因为有时 401 不会像前面提到的那样返回。

如果这以任何方式无法理解,我会添加任何信息。我的猜测是,要么我以错误的方式使用整个 NSURLCredential 内容,要么是通过首先获取 401 然后获取 200 进行身份验证的方式,因此无法消除。

下面是我的代码摘录:

loginCredential = [NSURLCredential credentialWithUser:@"foo" 
                                             password:@"bar"
                                          persistence:NSURLCredentialPersistencePermanent];

NSURLProtectionSpace *loginProtectionSpace = [[NSURLProtectionSpace alloc] initWithHost:@"foo.com"
                                                                                   port:8000 
                                                                               protocol:@"http" 
                                                                                  realm:nil 
                                                                   authenticationMethod:NSURLAuthenticationMethodBasic];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:loginCredential 
                                                    forProtectionSpace:loginProtectionSpace]; 
[loginProtectionSpace release];

loginCommunicator = [[LearnCommunicator alloc] initWithMethod:@"login-foo"     
                                                   credential:loginCredential];

通过此设置, NSURLConnection 的代表都可以正确调用

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection
{
    NSLog(@"connectionShouldUseCredentialStorage user: %@",[userCredential user]);
    return YES;
}

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    NSLog(@"canAuthenticateAgainstProtectionSpaceuser: %@",[userCredential user]);
    return YES;
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"didReceiveAuthenticationChallenge previousFailureCount: %i",[challenge previousFailureCount]);  
    if ([challenge previousFailureCount] == 0)
{
    NSLog(@"Challenging...");
    [[challenge sender] useCredential:userCredential forAuthenticationChallenge:challenge];
}
else
{
    NSLog(@"Username and password are incorrect");
    [[challenge sender] cancelAuthenticationChallenge:challenge];
}
}

任何输入都值得赞赏! 谢谢

编辑更新 01 这似乎是一个已知问题,很久以前就已经作为错误报告提交了 - 但尚未解决。 NSURLConnection 似乎不支持“Expect: 100-continue”标头,老实说,这是一个重大的失望。我在这个问题上花了很多时间,只是为了发现现在我必须重新处理所有事情。有关详细信息,请参阅错误报告:http://openradar.appspot.com/5188833

编辑更新 02 我当前解决此问题的方法是在使用电影数据进行大量 HTTP POST 之前简单地进行身份验证。由于我还必须上传一些较小的 XML 文件,因此我将使用它的先前身份验证来上传电影。这对我来说仍然感觉很丑陋,但我必须让事情继续下去......关于这个主题的任何意见/知道如何仍然值得赞赏。

I've been trying to solve this for some time now, but without success. Questions such as this one here or tuts on using authentication by apple and other blogs shed some light but not all.

My basic problem I'd like to solve is the following:

I'm successfully authenticating against my server by utilizing NSURLConnection its delegates and NSURLCredential with NSURLProtectionSpace and NSURLCredentialStorage. However even though I set the persistence of the NSURLCredential to NSURLCredentialPersistencePermanent I randomly get authentication challenges (401 and then 200) from my server after already having provided my credentials the first time - shouldn't that not be the case as NSURLCredentialPersistencePermanent lasts permanently? The random thing is what just doesn't make sense.

Sometimes it works and subsequent calls to the server return fine with 200. Then again it doesn't and 401 with 200 are returned. Mike Abdullah described the process nicely over here. So my first guess was that the process of returning 401 authenticating and getting a 200 is standard procedure and can't be eliminated. However sometimes I can eliminate the 401. So I seem to be missing out on something.

The requests I'm sending are some GETs and two POSTs. The thing is that one POST is uploading loads of data. When getting a 401 the data is still uploaded into nirvana after authentication it's uploaded again.

My fallback solution would be to prevent the data to be sent anyway when a 401 is received. I'm working on that right now, which seems tricky because sometimes 401 isn't returned as already mentioned before.

If this is in any way not comprehensible I'll add any info. My guess is either I'm using the whole NSURLCredential stuff in a wrong way or the way of authenticating by first getting a 401 and then a 200 is the way to go, thus can't be eliminated.

Excerpts from my code below:

loginCredential = [NSURLCredential credentialWithUser:@"foo" 
                                             password:@"bar"
                                          persistence:NSURLCredentialPersistencePermanent];

NSURLProtectionSpace *loginProtectionSpace = [[NSURLProtectionSpace alloc] initWithHost:@"foo.com"
                                                                                   port:8000 
                                                                               protocol:@"http" 
                                                                                  realm:nil 
                                                                   authenticationMethod:NSURLAuthenticationMethodBasic];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:loginCredential 
                                                    forProtectionSpace:loginProtectionSpace]; 
[loginProtectionSpace release];

loginCommunicator = [[LearnCommunicator alloc] initWithMethod:@"login-foo"     
                                                   credential:loginCredential];

With this setup the delegates of NSURLConnection get all called correctly

- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection
{
    NSLog(@"connectionShouldUseCredentialStorage user: %@",[userCredential user]);
    return YES;
}

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    NSLog(@"canAuthenticateAgainstProtectionSpaceuser: %@",[userCredential user]);
    return YES;
}

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"didReceiveAuthenticationChallenge previousFailureCount: %i",[challenge previousFailureCount]);  
    if ([challenge previousFailureCount] == 0)
{
    NSLog(@"Challenging...");
    [[challenge sender] useCredential:userCredential forAuthenticationChallenge:challenge];
}
else
{
    NSLog(@"Username and password are incorrect");
    [[challenge sender] cancelAuthenticationChallenge:challenge];
}
}

Any input appreciated!
Thx

EDIT UPDATE 01 This seems to be a known issue, which was already filed as bug report - a long time ago - but hasn't been resolved. NSURLConnection does not seem to support "Expect: 100-continue" header, which quite honestly is a major let down. I've been working hours on this issue just to find out now that I will have to rework everything. See the bug report for detailed info: http://openradar.appspot.com/5188833

EDIT UPDATE 02 My current workaround for this issue is to simply do an authentication right before going for the huge HTTP POST with movie data. As I have to upload some minor XML file aswell I'll use it's prior authentication for the movie upload. This still feels ugly to me, but I have to get things going... Any input/know how on this topic is still appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文