在用UIWebView的时候,如果访问需要http authentication,那么网页将无法显示。原因是UIWebView不会检测到网络设置,如代理设置,需要http认证等。
首先我们来说一下网络在代理环境中的authentication,如何让UIWebView正常工作。
由于UIWebView不会自动检测代理设置,所以解决方法是在UIWebViewDelegate方法中用NSURLConnect去连接到网络中任一网站,在NSURLConnectionDelegate接口中处理代理设置,在这儿需要代理用户名与密码。步骤如下:
1. 用NSURLConnect连接任一网站
1 | NSURLRequest *req = [NSURLRequest requestWithURL:url |
2 | cachePolicy:NSURLRequestReloadIgnoringCacheData |
4 | [[NSURLConnection alloc] initWithRequest:req delegate:self]; |
2. connection:didReceiveAuthenticationChallenge方法中处理代理设置
01 | - ( void )connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; |
04 | if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLProtectionSpaceHTTPProxy]) |
07 | if ([challenge previousFailureCount] == 0) { |
09 | [[challenge sender] useCredential:[NSURLCredential credentialWithUser:AUTH_USERNAME password:AUTH_PASSWORD persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge]; |
11 | [[challenge sender] cancelAuthenticationChallenge:challenge]; |
这下你的代理设置就保存了,因为用的是NSURLCredentialPersistencePermanent,以后在用UIWebView的时候就可以正常显示内容了。
更为完美的解决方案是NSURLProtocol参看:http://kadao.dir.bg/cocoa.htm
还有一种方法就是用ASIHttpRequest,开启
1 | request.shouldPresentProxyAuthenticationDialog = YES; |
2 | [request setUseKeychainPersistence:YES]; |
这样detect到代理的时候就会弹出输入框加要用户输入用户名与密码,且保存在keychain里,下次运行不需要再输 。
接着我们来说一下如果网站需要http basic authentication,如何让UIWebView正常工作。
经过google我发现了下面这种方法:
需要http认证,其实就是在每次请求的时候需要在http头加入用户名与密码,保证这次请求的合法性。最开始的时候,我也是采用上面的方法,就是每次UIWebView开始请求的时候先用NSURLConnect去连接这个请求,在其 connection:didReceiveAuthenticationChallenge方法中处理用户名与密码。这种处理方法会两次访问同一个 url且速度很慢。然后我就用了新的方法,即在NSURLRequest中加入Authorization字段,代码如下:
1 | NSURL *url = [NSURL URLWithString:yourUrlStr]; |
2 | NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url]; |
3 | NSString *authString = [[[NSString stringWithFormat:@ "%@:%@" , username, password] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding]; |
5 | authString = [NSString stringWithFormat: @ "Basic %@" , authString]; |
7 | [req setValue:authString forHTTPHeaderField:@ "Authorization" ]; |
其中username与password就是需要的用户名与密码。
网上有人写了一个NSMutableURLRequest的category,用起来也方便,随便也分享给大家。https://github.com/oscardelben/UIWebViewBasicAuth
在这儿我们得注意了:在头中加Authorization字段,我在iOS5中测试了, 通过这种方式request的UIWebView是不能成功显示网页的。没有iOS3与4测试,我猜测是以前的OS可以用这种方法。但是如果用 NSURLConnection去request,这种方法是可行的,能返回正确的html,但是image这些不能显示。UIWebView是基于 NSURL loading system的,理论上应是可行的,但是测试结果是不行。
即然这种方法不适用,那就得另寻方法。经过在网上找资料发现,如果把用户名与密码写在url里,那么就可以在UIWebView中正常访问。代码如下:
1 | NSString *URLString = [[NSString stringWithFormat:@ "http://%@:%@@%@" , @ "username" , @ "password" , [urlStr substringFromIndex:7]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; |
2 | NSURL *url = [NSURL URLWithString:URLString]; |
3 | NSURLRequest *req = [NSURLRequest requestWithURL:url |
4 | cachePolicy:NSURLRequestReloadIgnoringCacheData |
6 | webView loadRequest:req]; |
我在iPad1上测试可行,iPhone4上行,iPad与iPhone模拟器上都行,在iPad2上测试则不行,OS都是iOS5.
接在我在研究能通用方法,就是NSURL loading system。还在研究当中,有结果了再公布。
有了上面两种方法介绍,那么在有代理网络环境下去访问需要用户名与密码认识的网站,就可以完全正常了。
ASIWebPageRequest也是一个不错的选择,可以同时处理proxy与Http Basic Authentication。
参考:
http://www.springenwerk.com/2008/11/i-am-currently-building-iphone.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html
文章出处:http://blog.csdn.net/favormm/article/details/6956588