有一大堆问题提出了这样的问题:我能让UIWebView
查看一个自签名的HTTPS网站吗?
答案总是涉及到以下两种情况:
NSURLRequest
的私有api调用:NSURLRequest
NSURLConnection
和委托canAuthenticateAgainstProtectionSpace
etc对我来说,这些行不通。
(1) -表示我无法成功提交到应用商店。
(2) -使用NSURLConnection意味着在接收到初始HTML页面后,必须从服务器获取的CSS、图像和其他内容不会加载。
有没有人知道如何使用UIWebView查看不涉及上述两种方法的自签名https网页?
或者-如果使用NSURLConnection
实际上可以用来呈现一个包含CSS、图像和其他所有内容的网页-那就太好了!
干杯,
伸展。
发布于 2012-07-26 15:06:55
我终于明白了!
你能做的是:
照常使用UIWebView
发起请求。然后-在webView:shouldStartLoadWithRequest
中-我们回复NO,并使用相同的请求启动一个NSURLConnection。
使用NSURLConnection
,您可以与自签名服务器通信,因为我们能够通过UIWebView
不可用的额外委托方法控制身份验证。因此,使用connection:didReceiveAuthenticationChallenge
,我们可以对自签名服务器进行身份验证。
然后,在connection:didReceiveData
中,我们取消NSURLConnection
请求,并使用UIWebView
再次启动相同的请求-现在可以工作了,因为我们已经通过了服务器身份验证:)
下面是相关的代码片段。
注意:您将看到的实例变量具有以下类型:
UIWebView *_web
NSURLConnection *_urlConnection
NSURLRequest *_request
(我对_request
使用了一个instance var,因为在我的例子中,它是一个包含大量登录详细信息的POST,但是如果需要的话,您可以改为使用传入的请求作为方法的参数。)
#pragma mark - Webview delegate
// Note: This method is particularly important. As the server is using a self signed certificate,
// we cannot use just UIWebView - as it doesn't allow for using self-certs. Instead, we stop the
// request in this method below, create an NSURLConnection (which can allow self-certs via the delegate methods
// which UIWebView does not have), authenticate using NSURLConnection, then use another UIWebView to complete
// the loading and viewing of the page. See connection:didReceiveAuthenticationChallenge to see how this works.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
{
NSLog(@"Did start loading: %@ auth:%d", [[request URL] absoluteString], _authenticated);
if (!_authenticated) {
_authenticated = NO;
_urlConnection = [[NSURLConnection alloc] initWithRequest:_request delegate:self];
[_urlConnection start];
return NO;
}
return YES;
}
#pragma mark - NURLConnection delegate
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"WebController Got auth challange via NSURLConnection");
if ([challenge previousFailureCount] == 0)
{
_authenticated = YES;
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
} else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"WebController received response via NSURLConnection");
// remake a webview call now that authentication has passed ok.
_authenticated = YES;
[_web loadRequest:_request];
// Cancel the URL connection otherwise we double up (webview + url connection, same url = no good!)
[_urlConnection cancel];
}
// We use this method is to accept an untrusted site which unfortunately we need to do, as our PVM servers are self signed.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
我希望这能帮助其他人解决我遇到的同样的问题!
发布于 2013-02-26 02:59:14
Stretch的答案似乎是一个很好的变通方法,但它使用的是过时的API。因此,我认为它可能值得对代码进行升级。
对于这个代码示例,我将例程添加到包含我的UIWebView的ViewController中。我把我的UIViewController做成了UIWebViewDelegate和NSURLConnectionDataDelegate。然后我添加了两个数据成员:_Authenticated和_FailedRequest。这样,代码看起来就像这样:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
BOOL result = _Authenticated;
if (!_Authenticated) {
_FailedRequest = request;
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
return result;
}
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURL* baseURL = [_FailedRequest URL];
if ([challenge.protectionSpace.host isEqualToString:baseURL.host]) {
NSLog(@"trusting connection to host %@", challenge.protectionSpace.host);
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else
NSLog(@"Not trusting connection to host %@", challenge.protectionSpace.host);
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)pResponse {
_Authenticated = YES;
[connection cancel];
[_WebView loadRequest:_FailedRequest];
}
当我加载视图时,我将_Authenticated设置为NO,并且没有重置它。这似乎允许UIWebView向同一站点发出多个请求。我没有尝试切换网站,也没有试图回来。这可能会导致需要重置_Authenticated。此外,如果您要切换站点,您应该为_Authenticated保留一个字典(每个主机一个条目),而不是BOOL。
发布于 2014-02-12 22:28:01
这是灵丹妙药!
BOOL _Authenticated;
NSURLRequest *_FailedRequest;
#pragma UIWebViewDelegate
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
BOOL result = _Authenticated;
if (!_Authenticated) {
_FailedRequest = request;
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[urlConnection start];
}
return result;
}
#pragma NSURLConnectionDelegate
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURL* baseURL = [NSURL URLWithString:@"your url"];
if ([challenge.protectionSpace.host isEqualToString:baseURL.host]) {
NSLog(@"trusting connection to host %@", challenge.protectionSpace.host);
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else
NSLog(@"Not trusting connection to host %@", challenge.protectionSpace.host);
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)pResponse {
_Authenticated = YES;
[connection cancel];
[self.webView loadRequest:_FailedRequest];
}
- (void)viewDidLoad{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"your url"];
NSURLRequest *requestURL = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestURL];
// Do any additional setup after loading the view.
}
https://stackoverflow.com/questions/11573164
复制相似问题