NSURLConnection和NSMutableURLRequestvalidation
我有一个iOS应用程序,它将提交用户名和密码到一个网站,并检索按下“login”后加载的网页的HTML代码: https : //grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx ?。
表单数据字段如下:
__LASTFOCUS, __EVENTTARGET, __EVENTARGUMENT, __VIEWSTATE, __EVENTVALIDATION, ctl00$ContentPlaceHolder$Username, ctl00$ContentPlaceHolder$Password, ctl00$ContentPlaceHolder$lstDomains, ctl00$ContentPlaceHolder$LogonButton, PageUniqueId
这是我到目前为止的代码:
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];
但是,总是返回一个错误页面。 我究竟做错了什么? 我还实施了以下内容:
-(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"); }
}
但是这个方法从来不叫!
我的视图控制器符合:
NSURLConnectionDelegate,NSURLAuthenticationChallengeSender,NSURLConnectionDataDelegate
谢谢!
一些想法:
-
我对
__VIEWSTATE
和__EVENTVALIDATION
的保留字符的存在感到惊讶。 根据x-www-form-urlencoded
规范 ,你应该是除了*
,-
,以外的字符百分比转义字符.
,0
–9
,A
–Z
,_
和a
–z
。我的
POST
值的标准百分比转义例程是:- (NSString *)percentEscapeString:(NSString *)string { NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, (CFStringRef)@" ", (CFStringRef)@":/?@!$&'()*+,;=", kCFStringEncodingUTF8)); return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"]; }
-
我不确定这是至关重要的,但是你错过了
=
字符。 所以,而不是__LASTFOCUS&...
,我希望__LASTFOCUS=&...
将这两点拉到一起,所得到的有效载荷应该如下所示:
__LASTFOCUS =&__ EVENTTARGET =&__ EVENTARGUMENT =&__ VIEWSTATE =%2FwEPDwUJNTkxNzI3MDIzD2QWAmYPZBYCAgMPZBYGAgEPZBYCAgkPZBYCAgEPZBYIAgMPFgIeB1Zpc2libGVoZAIFDxYCHwBoZAIHDxYCHwBoZAIJDxYCHgVzdHlsZQUjdmVydGljYWwtYWxpZ246bWlkZGxlO2Rpc3BsYXk6bm9uZTtkAgMPDxYCHwBoZGQCBQ9kFghmD2QWAgINDxYCHgVjbGFzcwUQc2luZ2xlU2Nob29sTGlzdBYCAgEPZBYCAgEPEGQPFgFmFgEQBQ5EZWZhdWx0IERvbWFpbgUIUGlubmFjbGVnZGQCAg9kFgICEw9kFgICAQ9kFgICAQ8QZGQWAGQCBw8PFgIeBFRleHQFIFBpbm5hY2xlIEdyYWRlIDIwMTIgV2ludGVyIEJyZWFrZGQCCA8PFgIfAwU3Q29weXJpZ2h0IChjKSAyMDEzIEdsb2JhbFNjaG9sYXIuICBBbGwgcmlnaHRzIHJlc2VydmVkLmRkZP%2Fl6irI9peZfyqpKjk3fwLuEbos&__ EVENTVALIDATION =%2FwEWBgKjnbqUCQLnksmgAQKTpbWbDgLB5%2BKIBAL4xb20BAK20ZqiCel6sQLBsF1W3XHOxpgq%2BtJj%2BRx2&ctl00%24ContentPlaceHolder%24Username = A&ctl00%24ContentPlaceHolder%24Password = B&ctl00%24ContentPlaceHolder%24lstDomains =尖峰&ctl00%24ContentPlaceHolder%24LogonButton =拍+在&PageUniqueId = a3113b01- cf2f-4081-8a1a-d8557e7347de
请注意,在该请求的正文中出现了百分比转义。 我通过查看查尔斯的请求来确定身体。
-
我很惊讶地看到
__VIEWSTATE
,__EVENTVALIDATION
和PageUniqueId
硬编码。 我很容易想象使用这些variables的固定值会有问题。 这完全取决于网站的编程方式。 我正在收集,你试图以编程方式访问不是一个Web服务的网站,而是一个HTML界面,这可能是有问题的。在尝试login之前,您可能必须首先使用
Logins.aspx
执行GET
请求,然后从初始loginHTMLparsing这些值。 当试图以编程方式与Web服务器进行交互时,必须小心地调用Web浏览器所有的页面,因为将会有这样的服务器状态variables,您的应用程序也应该使用它们。 -
不相关,但是你不需要指定
Content-length
,因为NSURLConnection
会根据你的httpBody
的大小为你httpBody
。 -
如果您已经到了使用
cancelAuthenticationChallenge
的地步,请注意您应该确保else
子句调用cancelAuthenticationChallenge
或者continueWithoutCredentialForAuthenticationChallenge
cancelAuthenticationChallenge
。 你总是要打三种挑战方法之一。话虽如此,目前还不清楚
didReceiveAuthenticationChallenge
会被调用。 您的服务器可能会采用一些不是基于挑战的服务器应用程序级别身份validation。
底线,我们很难根据迄今为止提供的内容来诊断问题的根源。 我会联系HTML界面的作者,询问authentication过程的细节。