NSURLConnection和NSMutableURLRequest身份验证 [英] NSURLConnection and NSMutableURLRequest Authentication

查看:138
本文介绍了NSURLConnection和NSMutableURLRequest身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个iOS应用程序,它会向网站提交用户名和密码,并检索在登录后加载的网页的 HTML 代码: https://grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx ?。

I have an iOS application which will submit a username and password to a website and to retrieve the HTML code of the webpage which loads after pressing 'Sign in': https://grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx?.

表单数据字段如下:


__LASTFOCUS,__ EVENTTARGET,__ EVENTARGUMENT,__ reviewSTATE,__ EVENTVALIDATION,ctl00 $ ContentPlaceHolder $ Username,ctl00 $ ContentPlaceHolder $ Password,ctl00 $ ContentPlaceHolder $ lstDomains,ctl00 $ ContentPlaceHolder $ LogonButton,PageUniqueId

这是我到目前为止的代码:

This is the code that I have so far:

NSURL * url = [NSURL URLWithString:@ https://grades.bsd405.org/Pinnacle/Gradebook/ Logon.aspx?RETURNURL =%2fPinnacl e%2fGradebook%2fDefault.aspx ];

NSURL * url = [NSURL URLWithString:@"https://grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx?ReturnUrl=%2fPinnacle%2fGradebook%2fDefault.aspx"];

NSString *post = @"__LASTFOCUS&__EVENTTARGET&__EVENTARGUMENT&__VIEWSTATE=/wEPDwUJNTkxNzI3MDIzD2QWAmYPZBYCAgMPZBYGAgEPZBYCAgkPZBYCAgEPZBYIAgMPFgIeB1Zpc2libGVoZAIFDxYCHwBoZAIHDxYCHwBoZAIJDxYCHgVzdHlsZQUjdmVydGljYWwtYWxpZ246bWlkZGxlO2Rpc3BsYXk6bm9uZTtkAgMPDxYCHwBoZGQCBQ9kFghmD2QWAgINDxYCHgVjbGFzcwUQc2luZ2xlU2Nob29sTGlzdBYCAgEPZBYCAgEPEGQPFgFmFgEQBQ5EZWZhdWx0IERvbWFpbgUIUGlubmFjbGVnZGQCAg9kFgICEw9kFgICAQ9kFgICAQ8QZGQWAGQCBw8PFgIeBFRleHQFIFBpbm5hY2xlIEdyYWRlIDIwMTIgV2ludGVyIEJyZWFrZGQCCA8PFgIfAwU3Q29weXJpZ2h0IChjKSAyMDEzIEdsb2JhbFNjaG9sYXIuICBBbGwgcmlnaHRzIHJlc2VydmVkLmRkZP/l6irI9peZfyqpKjk3fwLuEbos&__EVENTVALIDATION=/wEWBgKjnbqUCQLnksmgAQKTpbWbDgLB5+KIBAL4xb20BAK20ZqiCel6sQLBsF1W3XHOxpgq+tJj+Rx2&ctl00$ContentPlaceHolder$Username=TESTUSERNAME&ctl00$ContentPlaceHolder$Password=TESTPASSWORD&ctl00$ContentPlaceHolder$lstDomains=Pinnacle&ctl00$ContentPlaceHolder$LogonButton=Signin&PageUniqueId=2dacba26-bb0d-412f-b06a-e02caf039c4b";

NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

[self clearCookiesForURL:url];
[request setURL:url];

[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];

但是,始终会返回错误页面。我究竟做错了什么?
我还实现了以下内容:

However, an error page is always returned. What am I doing wrong? Also I implemented the following:

-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"HEREEE");
if ([challenge previousFailureCount] == 0) {
    NSLog(@"received authentication challenge");
    NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"USERNAME"
                                                                password:@"PASSWORD"
                                                             persistence:NSURLCredentialPersistenceForSession];
    NSLog(@"credential created");
    [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
    NSLog(@"responded to authentication challenge");
}
else {
    NSLog(@"previous authentication failure");
}

}

但是这种方法永远不会被调用!

But this method is never called!

我的视图控制器符合:

NSURLConnectionDelegate,NSURLAuthenticationChallengeSender,NSURLConnectionDataDelegate

My View controller conforms to :
NSURLConnectionDelegate,NSURLAuthenticationChallengeSender,NSURLConnectionDataDelegate

谢谢!

推荐答案

有几点想法:


  1. 我对 __ VIEWSTATE __ EVENTVALIDATION 。根据 x-www-form-urlencoded spec ,你应该是转义 * 以外的字符的百分比, - 0 - 9 A - Z _ a - z

  1. I'm surprised by the presence of reserved characters in __VIEWSTATE and __EVENTVALIDATION. Per the x-www-form-urlencoded spec, you should be percent escaping characters other than *, -, ., 0-9, A-Z, _ and a-z.

我的标准百分比逃避程序对于 POST 值为:

My standard percent-escaping routine for POST values is:

- (NSString *)percentEscapeString:(NSString *)string
{ 
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)string,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                 kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}


  • 我不确定这是至关重要的,但你错过了 = 字符。所以,而不是 __ LASTFOCUS& ... ,我希望 __ LASTFOCUS =& ...

  • I'm not sure it's critical, but you're missing = characters. So, rather than __LASTFOCUS&..., I'd expect __LASTFOCUS=&....

    将这两个点拉在一起,得到的有效载荷应如下所示:

    Pulling these two points together, the resulting payload should look something like:

    
    __LASTFOCUS=&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwUJNTkxNzI3MDIzD2QWAmYPZBYCAgMPZBYGAgEPZBYCAgkPZBYCAgEPZBYIAgMPFgIeB1Zpc2libGVoZAIFDxYCHwBoZAIHDxYCHwBoZAIJDxYCHgVzdHlsZQUjdmVydGljYWwtYWxpZ246bWlkZGxlO2Rpc3BsYXk6bm9uZTtkAgMPDxYCHwBoZGQCBQ9kFghmD2QWAgINDxYCHgVjbGFzcwUQc2luZ2xlU2Nob29sTGlzdBYCAgEPZBYCAgEPEGQPFgFmFgEQBQ5EZWZhdWx0IERvbWFpbgUIUGlubmFjbGVnZGQCAg9kFgICEw9kFgICAQ9kFgICAQ8QZGQWAGQCBw8PFgIeBFRleHQFIFBpbm5hY2xlIEdyYWRlIDIwMTIgV2ludGVyIEJyZWFrZGQCCA8PFgIfAwU3Q29weXJpZ2h0IChjKSAyMDEzIEdsb2JhbFNjaG9sYXIuICBBbGwgcmlnaHRzIHJlc2VydmVkLmRkZP%2Fl6irI9peZfyqpKjk3fwLuEbos&__EVENTVALIDATION=%2FwEWBgKjnbqUCQLnksmgAQKTpbWbDgLB5%2BKIBAL4xb20BAK20ZqiCel6sQLBsF1W3XHOxpgq%2BtJj%2BRx2&ctl00%24ContentPlaceHolder%24Username=a&ctl00%24ContentPlaceHolder%24Password=b&ctl00%24ContentPlaceHolder%24lstDomains=Pinnacle&ctl00%24ContentPlaceHolder%24LogonButton=Sign+in&PageUniqueId=a3113b01-cf2f-4081-8a1a-d8557e7347de
    

    注意在该请求的整个主体中逃逸的百分比的出现。我通过查看 Charles 中的请求来确定身体。

    Note the occurrences of percent escaping throughout the body of that request. I determined the body by looking at the request in Charles.

    我很惊讶地看到 __ VIEWSTATE __ EVENTVALIDATION PageUniqueId 像这样硬编码。我可以很容易地想象,对这些变量使用固定值会有问题。这完全取决于网站的编程方式。我正在收集您尝试以编程方式访问不是Web服务的网站,而是HTML界面,这可能会有问题。

    I'm surprised to see __VIEWSTATE, __EVENTVALIDATION, and PageUniqueId hard-coded like this. I could easily imagine that it would be problematic to use fixed values for these variables. It depends entirely upon how the web site was programmed. I'm gathering that you're trying to programmatically access a web site that isn't a web service, but rather is a HTML interface, and that can be problematic.

    在尝试登录之前,您可能必须首先使用 Logins.aspx 执行 GET 请求,并解析这些值从那个初始登录HTML。当尝试以编程方式与Web服务器交互时,您必须小心地将所有页面调用为Web浏览器,因为这样的服务器状态变量也应该是您的应用程序应该使用的。

    You probably have to perform GET request with Logins.aspx first, before trying to log in, and parse these values from that initial login HTML. When trying to programmatically interact with web server, you have to be careful to call all of the pages a web browser would, as there are going to be server state variables like this that your app should be using, too.

    不相关,但您不需要指定 Content-length ,因为 NSURLConnection 将根据 httpBody 的大小为您提供。

    Unrelated, but you don't need to specify Content-length, as NSURLConnection will supply that for you based upon the size of your the httpBody.

    如果你到了使用 didReceiveAuthenticationChallenge 的程度,请注意你应该确保 else 子句调用 cancelAuthenticationChallenge continueWithoutCredentialForAuthenticationChallenge 。你总是要调用这三种挑战方法中的一种。

    If you get to the point of using your didReceiveAuthenticationChallenge, note that you should ensure that the else clause calls cancelAuthenticationChallenge or continueWithoutCredentialForAuthenticationChallenge. You always have to call one of these three challenge methods.

    话虽如此,但不清楚 didReceiveAuthenticationChallenge 会不会完全被召唤。您的服务器可能正在使用一些不是基于挑战的服务器应用级身份验证。

    Having said that, it's not clear that didReceiveAuthenticationChallenge would be called at all. Your server could be employing some server app-level authentication that is not a challenge-based.

    底线,它是我们很难根据迄今为止提供的内容来诊断问题的根源。我会联系HTML界面的作者并询问身份验证过程的具体细节。

    Bottom line, it's hard for us to diagnose the root of the problem on the basis of what's been provided thus far. I would contact the author of the HTML interface and inquire about specifics of the authentication process.

    这篇关于NSURLConnection和NSMutableURLRequest身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆