ios - NSURLConnection 和 NSMutableURLRequest 身份验证
<p><p>我有一个 iOS 应用程序,它将向网站提交用户名和密码,并检索按“登录”后加载的网页的 <strong>HTML</strong> 代码:<a href="https://grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx" rel="noreferrer noopener nofollow">https://grades.bsd405.org/Pinnacle/Gradebook/Logon.aspx</a> ?.</p>
<p><strong>表单数据字段如下:</strong></p>
<p><code>
__LASTFOCUS, __EVENTTARGET, __EVENTARGUMENT, __VIEWSTATE, __EVENTVALIDATION, ctl00$ContentPlaceHolder$Username, ctl00$ContentPlaceHolder$Password, ctl00$ContentPlaceHolder$lstDomains, ctl00$ContentPlaceHolder$LogonButton, PageUniqueId
</code></p>
<p>这是我目前的代码:</p>
<p>NSURL * url = ;</p>
<pre><code>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 = ;
NSString *postLength = ];
NSMutableURLRequest *request = [ init];
;
;
;
;
;
;
NSURLConnection *conn = [initWithRequest:request delegate:self];
</code></pre>
<p>但是,总是返回错误页面。我究竟做错了什么?
我还实现了以下内容:</p>
<pre><code>-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(@"HEREEE");
if ( == 0) {
NSLog(@"received authentication challenge");
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"USERNAME"
password:@"PASSWORD"
persistence:NSURLCredentialPersistenceForSession];
NSLog(@"credential created");
[ useCredential:newCredential forAuthenticationChallenge:challenge];
NSLog(@"responded to authentication challenge");
}
else {
NSLog(@"previous authentication failure");
}
</code></pre>
<p>}</p>
<p>但是这个方法永远不会被调用!</p>
<p>我的 ViewController 符合:<br/>
NSURLConnectionDelegate,NSURLAuthenticationChallengeSender,NSURLConnectionDataDelegate</p>
<p>谢谢!</p></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>一些想法:</p>
<ol>
<li><p>我对 <code>__VIEWSTATE</code> 和 <code>__EVENTVALIDATION</code> 中存在保留字符感到惊讶。根据 <a href="http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm" rel="noreferrer noopener nofollow">the <code>x-www-form-urlencoded</code> spec</a> , 你应该使用百分比转义字符而不是 <code>*</code>, <code>-</code>, <code>.</code>, <code>0</code>-<code>9</code>、<code>A</code>-<code>Z</code>、<code>_</code> 和 <code>a</code>-<code>z</code>。</p>
<p><code>POST</code> 值的标准百分比转义例程是:</p>
<pre><code>- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)@" ",
(CFStringRef)@":/?@!$&'()*+,;=",
kCFStringEncodingUTF8));
return ;
}
</code></pre> </li>
<li><p>我不确定这是否严重,但您缺少 <code>=</code> 个字符。所以,我希望 <code>__LASTFOCUS=&...</code> 而不是 <code>__LASTFOCUS&...</code>。</p>
<p>将这两点放在一起,生成的有效负载应该如下所示:</p>
<pre>__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
</pre>
<p>请注意整个请求正文中出现的百分比转义。我通过查看 <a href="http://www.charlesproxy.com" rel="noreferrer noopener nofollow">Charles</a> 中的请求确定了正文.</p></li>
<li><p>我很惊讶地看到 <code>__VIEWSTATE</code>、<code>__EVENTVALIDATION</code> 和 <code>PageUniqueId</code> 是这样硬编码的。我可以很容易地想象,对这些变量使用固定值会有问题。这完全取决于网站的编程方式。我收集到您正在尝试以编程方式访问不是 Web 服务而是 HTML 界面的网站,这可能会出现问题。</p>
<p>在尝试登录之前,您可能必须先使用 <code>Logins.aspx</code> 执行 <code>GET</code> 请求,然后从初始登录 HTML 中解析这些值。在尝试以编程方式与 Web 服务器交互时,您必须小心调用 Web 浏览器会调用的所有页面,因为您的应用也应该使用这样的服务器状态变量。</p></li>
<li><p>不相关,但您不需要指定 <code>Content-length</code>,因为 <code>NSURLConnection</code> 会根据您的 <code> 大小为您提供>httpBody</code>.</p></li>
<li><p>如果您使用 <code>didReceiveAuthenticationChallenge</code>,请注意您应确保 <code>else</code> 子句调用 <code>cancelAuthenticationChallenge</code> 或<code>continueWithoutCredentialForAuthenticationChallenge</code>。您总是必须调用这三种挑战方法之一。</p>
<p>话虽如此,但根本不清楚 <code>didReceiveAuthenticationChallenge</code> 是否会被调用。您的服务器可能正在使用一些不基于质询的服务器应用级身份验证。</p></li>
</ol>
<p>归根结底,我们很难根据迄今为止提供的信息来诊断问题的根源。我会联系HTML界面的作者,询问认证过程的细节。</p></p>
<p style="font-size: 20px;">关于ios - NSURLConnection 和 NSMutableURLRequest 身份验证,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/23398368/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/23398368/
</a>
</p>
页:
[1]