http media streaming over https by MVMoviePlayerViewController for iphone - iphone

I want to implement a function of http media streaming over https by MVMoviePlayerViewController. I try to access https server by NSURLConnection then open media by MVMoviePlayerViewController. I can successfully open the image url by UIWebView through this method under simulator and device and open media url like mp3 and mp4 by MVMoviePlayerViewController under simulator. The strange thing is that I get failed to open media url by MVMoviePlayerViewController under device. The following are error log.
An instance 0x4b4650 of class AVPlayerItem was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
(
Context: 0x0, Property: 0x208c20> Context: 0x0, Property: 0xa8626b0>
The following are some of my code.
-(void)viewDidLoad
{
NSString *stringPath = [NSString stringWithFormat:#"https://xxxxx/xxx.mp4";
NSURL *urlPath = [NSURL URLWithString:[stringPath stringByAddingPercentEscapesUsingEncoding:NSUTF8St ringEncoding]];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:urlPath];
NSURLConnection *httpConnection = [[[NSURLConnection alloc] initWithRequest:urlRequest delegate:self] autorelease];
}
- (BOOL)connection : (NSURLConnection *)connection canAuthenticateAgainstProtectionSpace : (NSURLProtectionSpace *)protectionSpace
{
return YES;
}
- (void)connection : (NSURLConnection *)connection didReceiveAuthenticationChallenge : (NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] > 0)
{
return;
}
NSString *authenticationMethod = challenge.protectionSpace.authenticationMethod;
if ([authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTru st])
{
SecTrustRef secTrustRef = challenge.protectionSpace.serverTrust;
[challenge.sender useCredential:[NSURLCredential credentialForTrust:secTrustRef forAuthenticationChallenge:challenge];
}
else
{
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:#"adminr" password:#"admin" persistence:NSURLCredentialPersistenceForSession];
[challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];
}
}
- (void)connection : (NSURLConnection *)connection didReceiveResponse : (NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
assert([httpResponse isKindOfClass:[NSHTTPURLResponse class]]);
NSLog(#"didReceiveResponse, status code : %d", httpResponse.statusCode);
NSString *stringPath = [NSString stringWithFormat:#"%#", testPath];
NSURL *urlPath = [NSURL URLWithString:[stringPath stringByAddingPercentEscapesUsingEncoding:NSUTF8St ringEncoding]];
if ((httpResponse.statusCode / 100) == 2)
{
MPMoviePlayerViewController *movieViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:urlPath];
[self presentMoviePlayerViewControllerAnimated:movieView Controller];
}
}
STEPS TO REPRODUCE
using NSURLConnection API to connect to an untrusted certification https server.
I will receive didReceiveAuthenticationChallenge (NSURLConnection delegate) and get NSURLAuthenticationMethodServerTrust authenticationMethod. I use SecTrustRef and NSURLCredential to access to untrusted certification https server.
I will receive didReceiveAuthenticationChallenge (NSURLConnection delegate) and use NSURLCredential to set username and password to access to untrusted certification https server.
I all receive didReceiveResponse (NSURLConnection delegate) and get http response statusCode 200 OK.
I try to open https media url by MPMoviePlayerViewController API.

Related

How to Validate SSL certificate

I want to validate SSL certificate in my app and i am using AFNetworking for validating certificate.
For SSL validation i am using openssl,libcrypto.a and libssl.a
My problem is that validation process was complete with NSURLConnection delegate methods, but using AFNetworking its not working.
NSURL *url = [NSURL URLWithString:#"https://www.google.com"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:req];
[operation setCompletionBlockWithSuccess: ^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *stringResponse = [[NSString alloc] initWithData:responseObject
encoding:NSUTF8StringEncoding];
// [self.webView loadHTMLString:stringResponse baseURL:nil];
NSLog(#"Responce-->>%#",stringResponse);
} failure: ^(AFHTTPRequestOperation *operation, NSError *error) {
// [self.webView loadHTMLString:error.localizedDescription baseURL:nil];
NSLog(#"Responce-->>%#",error.localizedDescription);
}];
[operation start];
[operation setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge)
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
// By now, the OS will already have built a SecTrustRef instance for
// the server certificates; we just need to evaluate it
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecTrustResultType res;
OSStatus status = SecTrustEvaluate(serverTrust, &res);
bool verified = FALSE;
if (status == errSecSuccess && ((res == kSecTrustResultProceed) || (res == kSecTrustResultUnspecified)))
{
NSLog(#"iOS certificate chain validation for host %# passed", challenge.protectionSpace.host);
verified = verifyWithOpenSSL(serverTrust);
}
else
{
NSLog(#"iOS certificate chain validation for host %# failed", challenge.protectionSpace.host);
}
if (verified)
{
// If *both* verifications succeeded, then continue with the connection
NSURLCredential *successCredential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:successCredential
forAuthenticationChallenge:challenge];
}
else
{
[challenge.sender cancelAuthenticationChallenge:challenge];
}
} else {
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}];
This is a code of AFNetworking for validation, I don't know whether it is wrong or correct.
But this process was completely work with NSURLConnection.
So please help.
AFNetworking 2 makes this really easy. First, add your SSL certificate to your app bundle. The certificate should have a .cer extension. Second, set a securityPolicy for your operation:
operation.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
By default, AFNetworking will validate the remote certificate against the one bundled with your app, ensuring that the domain name is correct, that both were issued with the same keypair, and that the certificate chain is valid.

setDefaultCredential not working for UIWebView in iOS 7 but works fine in earlier iOS versions

I am currently using the following code to set default credentials for UIWebView. This works fine in iOS 6.1 and earlier. However, in iOS 7 Beta 6 it does not work at all.
The web pages that I am trying to load use Windows Authentication. I am able to open them in Safari in iOS 7. However, when I run the below code and then open the URL in a UIWebView, I get an empty white rectangle and nothing ever loads! Like I said, this works perfectly in iOS 6.1 and earlier.
I also tried a second approach that involves using NSURLConnectionDelegate to hand off the credentials. This second approach also works fine in iOS 6.1 and earlier, but is broken in iOS 7.
Does anyone know why this is happening? Similar experiences? Thoughts?
// Authenticate
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"myusername"
password:#"mypassword"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"mysite.com"
port:80
protocol:#"http"
realm:nil
authenticationMethod:NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
I had the same exact issue - an NSURLConnection to a Sharepoint site configured for Windows Authentication was working fine in iOS 6.1. In iOS 7 - regardless of whether I targeted and built the app for 6 or 7 - all authentications would seem to succeed (receiving the proper cookie) but still respond with a 401; all subsequent requests sent with the cookie would receive 401 as well.
I resolved the issue by dumping the didReceiveAuthenticationChallenge delegate protocol in favor of willSendRequestForAuthenticationChallenge. Implementing the 2nd delegate protocol means the first never gets called.
In your delegate, implement this delegate protocol:
- (void)connection:(NSURLConnection *)sender willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] > 0]) {
[[challenge sender] cancelAuthenticationChallenge:challenge];
}else{
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"username" password:#"password" persistence:NSURLPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
}
After I implemented this on a whim, my iOS 7 NTLM authentication issues disappeared.
Update: This issue appears to be fixed in iOS 7.0.3
I answered this in the Apple developer forum, but now that iOS7 is out of beta, I'll repost here. Currently Windows Authentication is broken in iOS7. I expect there will be a fix out shortly, but until then you can work around the problem by handling authentication challenges in your UIViewController that contains your UIWebView.
Essentially you
Make an NSURLRequest and NSURLConnection yourself
Handle the connection:didReceiveAuthenticationChallenge:
In the connection:didReceivedResponse manually load your data into the UIWebView
Below I'm loading a PDF, but the process works the same whatever your content type.
//Make sure you implement NSURLConnectionDelegate and NSURLConnectionDataDelegate in your header
#interface MyViewController ()
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#property (strong, nonatomic) NSURLConnection *conn;
#property (strong, nonatomic) NSMutableData *pdfData;
#end
#implementation MyViewController
//... all of your init and other standard UIViewController methods here...
//Method that loads UIWebview. You'll probably call this in viewDidLoad or somewhere similar...
- (void) loadWebView {
//Make Request manually with an NSURLConnection...
NSString *url = //Get your url
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
self.conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
//#pragma mark - NSURLConnectionDelegate
//Handle authentication challenge (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if([challenge previousFailureCount] == 0) {
NSString *username = //Get username
NSString *password = //Get password
//Use credentials to authenticate
NSURLCredential *cred = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
} else {
//Cancel authentication & connection
[[challenge sender] cancelAuthenticationChallenge:challenge];
[self.conn cancel];
self.conn = nil;
}
}
//#pragma mark - NSURLConnectionDataDelegate
//Received response (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
//Init data
self.pdfData = [NSMutableData data];
}
//Collect data as it comes in (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.pdfData appendData:data];
}
//Handle connection failure (NSURLConnectionDataDelegate)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//Clean up...
[self.conn cancel];
self.conn = nil;
self.pdfData = nil;
//TODO: Notify user and offer next step...
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//Finally, load data into UIWebview here (I'm loading a PDF)...
[self.webView loadData:self.pdfData MIMEType:#"application/pdf" textEncodingName:#"utf-8" baseURL:nil];
}
#end

iphone: secure restfull server "The certificate for this server is invalid

I am trying to consume secure restful service which gives error
Error = Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xxx.xxx.xxx.xxx” which could put your confidential information at risk."
working on xCode 4.2, where is the mistake or any step missing.
using following code
RegisterUser.f
#interface RegisterUser : UIViewController<UITextFieldDelegate,
UIScrollViewDelegate, NSURLConnectionDelegate>
RegisterUser.m
- (IBAction)SubmitBtnAction:(id)sender {
NSURL *url = [NSURL URLWithString:#"https://xx.xx.xx.xxx:8223/jaxrs/tunedoorgateway/getCountries"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if ([data length] >0 && error == nil)
{
NSLog(#"Data = %#", data);
// DO YOUR WORK HERE
}
else if ([data length] == 0 && error == nil)
{
NSLog(#"Nothing was downloaded.");
}
else if (error != nil){
NSLog(#"Error = %#", error);
}
}];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"This is canAuthenticateAgainstProtectionSpace");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
// if ([trustedHosts containsObject:challenge.protectionSpace.host])
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
NSLog(#"This is didReceiveAuthenticationChallenge");
// [[challenge sender] cancelAuthenticationChallenge:challenge];
}
I feel this might be because of DNS, something like your server is not registered.
Try using this for development:
Create an NSURLRequest+NSURLRequestSSLY.h file and add these lines to it
#import <Foundation/Foundation.h>
#interface NSURLRequest (NSURLRequestSSLY)
+(BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
#end
Create an NSURLRequest+NSURLRequestSSLY.m file and add these lines to it
#import "NSURLRequest+NSURLRequestSSLY.h"
#implementation NSURLRequest (NSURLRequestSSLY)
+(BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host
{
return YES;
}
#end
And don't forget to remove it before publishing as your app might get rejected.
The failure is not in your code. You are using a HTTPS server which does not provide a known certificate. If you have setup the server yourself you have to go and buy a singed certificate from one of the big certification authorities which are trusted by iOS and most other operating systems.
For development purposes you can test your REST service by ignoring the non-trusted certificate. Follow this guide for doing that: http://www.cocoanetics.com/2009/11/ignoring-certificate-errors-on-nsurlrequest/
But for production use I recommend you do not use this method since it will bring a security leak to your application. If you do ignore security you can also just use HTTP instead of HTTPS.
I have tried several way and found out it is related with apple developer centre certificate.
Upgrade your provisioning and try it again. I have tried posting data with iPad, iPhone 5 and 5S but iPhone 4.
When I have update my provisioning and installing on my iPhone 4, works with now issue.

iphone uiwebview authentication challenge keeps firing when signed in

i have recently implemented authentication challenge log in through the iPhones UIWebView. i've got it working to the point where i get challenged then i present an alert with text fields, then send the data to the site that needs authentication.
i have not yet tried to use this on anything else besides my netgear router. But my problem is when i navigate through the settings for the router, the authentication challenge gets called, thus presenting the alert even though the user is logged in.
below is the code i'm using, any advice would be grately appreciated
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"Did start loading: %# auth:%d", [[request URL] absoluteString], _authed);
myRequest=[request copy];
if (_authed) {
NSLog(#"_authed");
_authed = NO;
// pretty sure i'm leaking here, leave me alone... i just happen to leak sometimes
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return YES;
}
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return YES;}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"protection space %#", protectionSpace.authenticationMethod);
//if(![protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]){
return NO;
//}
//else{
// return YES;
//}
//[protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] || [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic];}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;{NSLog(#"received response via nsurlconnection %#", connection);
NSLog(#"got auth challange %#", challenge);
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = NO;
/*NSString *aarrgghh=[NSString stringWithFormat:#"%#",connection];
NSString *searchForMe = #"login";
NSLog (#"arrgghhh %#",aarrgghh);
NSRange range = [aarrgghh rangeOfString:searchForMe];*/
if ([challenge previousFailureCount] <=1) {
//present alert with text fields for credentials
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
}}
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
NSLog(#"Challenge cancelled");}
//`-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
NSLog(#"received data");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;{
NSLog(#"received response via nsurlconnection %#", response);
// THIS IS WHERE YOU SET MAKE THE NEW REQUEST TO UIWebView, which will use the new saved auth info
if(_authed){
//NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:self.webView.request.URL.absoluteString]];
[webView loadRequest:myRequest];
}
}
`
Might be a simpler way to do this, but this is what worked for me.
First off, when shouldStartLoadWithRequest returns YES, that tells UIWebView to create NSURLConnections and run them for you . Since you can't assign a delegate to this connection, that's not going to work. If you want to handle authentication via a NSURLConnectionDelegate, then shouldStartLoadWithRequest should always return NO for that UIWebView.
So you need to handle the connection yourself. Fire off an NSURLConnection with the request and use the rest of the NSURLConnection delegate methods to handle the loading (e.g. keep track of the MIME type and build up an NSMutableData)
Finally, when you get to connectionDidFinishLoading, you can call UIWebView's loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL with the NSData your connection downloaded.

UrlConnection Iphone

I am trying to get data from a server using the following code.
+ (NSString *) getData:(NSString *)methodName parameters:(NSDictionary *) parameters error:(NSError **)error
{
NSString *body = [UdoziProxy getRequestBody:methodName parameters:parameters];
NSMutableURLRequest *request = [UdoziProxy createRequest:body];
// Send the request .
NSHTTPURLResponse *urlResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:error];
if (responseData == nil || error !=nil) {
return nil;
}
return [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
}
It works fine when the server is running but when I stop the server deliberately, the responseData object has still value and is not nil. How can I handle the situation where either the connection is lost or the server is down ?
You need to set the cache policy on your NSURLRequest object. If the synchronous API still doesn't honour that, you need to switch to using the asynchronous API and throw away the cache request object when you receive it. If that doesn't work, then maybe your network has a transparent proxy which is doing some caching for you.
you have to implement NSURLConnection delegates in
you can get failure status in
the following delegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
responseData =nil
}
there you have to make the recieved data to nil value
also its safe to
get data in
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{ }
which indicates that the connection is finished