UIWebView 处理 authentication 方法

鉴客 发布于 2012/02/11 18:37
阅读 2K+
收藏 3
iOS

在用UIWebView的时候,如果访问需要http authentication,那么网页将无法显示。原因是UIWebView不会检测到网络设置,如代理设置,需要http认证等。

首先我们来说一下网络在代理环境中的authentication,如何让UIWebView正常工作

由于UIWebView不会自动检测代理设置,所以解决方法是在UIWebViewDelegate方法中用NSURLConnect去连接到网络中任一网站,在NSURLConnectionDelegate接口中处理代理设置,在这儿需要代理用户名与密码。步骤如下:

1. 用NSURLConnect连接任一网站

NSURLRequest *req = [NSURLRequest requestWithURL:url  
                     cachePolicy:NSURLRequestReloadIgnoringCacheData  
                     timeoutInterval:20.0];  
[[NSURLConnection alloc] initWithRequest:req delegate:self];

2. connection:didReceiveAuthenticationChallenge方法中处理代理设置

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;  
{     
        //如果是http代理,其它代理方法类似  
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLProtectionSpaceHTTPProxy])  
    {  
          
        if ([challenge previousFailureCount] == 0) {  
            /* SET YOUR credentials, i'm just hard coding them in, tweak as necessary */  
            [[challenge sender] useCredential:[NSURLCredential credentialWithUser:AUTH_USERNAME password:AUTH_PASSWORD persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge];  
        } else {  
            [[challenge sender] cancelAuthenticationChallenge:challenge];   
        }  
    }  
}  

这下你的代理设置就保存了,因为用的是NSURLCredentialPersistencePermanent,以后在用UIWebView的时候就可以正常显示内容了。

更为完美的解决方案是NSURLProtocol参看:http://kadao.dir.bg/cocoa.htm

还有一种方法就是用ASIHttpRequest,开启

request.shouldPresentProxyAuthenticationDialog = YES;  
[request setUseKeychainPersistence:YES];  

这样detect到代理的时候就会弹出输入框加要用户输入用户名与密码,且保存在keychain里,下次运行不需要再输 。

接着我们来说一下如果网站需要http basic authentication,如何让UIWebView正常工作

经过google我发现了下面这种方法:

需要http认证,其实就是在每次请求的时候需要在http头加入用户名与密码,保证这次请求的合法性。最开始的时候,我也是采用上面的方法,就是每次UIWebView开始请求的时候先用NSURLConnect去连接这个请求,在其 connection:didReceiveAuthenticationChallenge方法中处理用户名与密码。这种处理方法会两次访问同一个 url且速度很慢。然后我就用了新的方法,即在NSURLRequest中加入Authorization字段,代码如下:

NSURL *url = [NSURL URLWithString:yourUrlStr];      
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];  
NSString *authString = [[[NSString stringWithFormat:@"%@:%@", username, password] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];  
      
authString = [NSString stringWithFormat: @"Basic %@", authString];  
      
[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中正常访问。代码如下:

NSString *URLString = [[NSString stringWithFormat:@"http://%@:%@@%@", @"username", @"password", [urlStr substringFromIndex:7]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];  
NSURL *url = [NSURL URLWithString:URLString];  
NSURLRequest *req = [NSURLRequest requestWithURL:url  
                                     cachePolicy:NSURLRequestReloadIgnoringCacheData  
                                 timeoutInterval:20.0];  
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

加载中
0
Mondeo
Mondeo
开源中国的iOS客户端最新源码哪里有?谢谢了
返回顶部
顶部