4

i am having problems with playing movie from URL that has basic http authentification.

Here is code:

NSURLCredential *credential = [[NSURLCredential alloc]
                               initWithUser:@"user"
                               password:@"password"
                               persistence:NSURLCredentialPersistenceForSession];

NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                             initWithHost:@"moze.dyndns.org"
                                             port:80
                                             protocol:@"http"
                                             realm:nil
                                             authenticationMethod:NSURLAuthenticationMethodHTTPBasic];

[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];


NSURL *videoURL = [NSURL URLWithString:@"http://moze.dyndns.org/test/test.mov"];
moviePlayerController = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
[moviePlayerController.view setFrame:self.view.bounds];
[self.view addSubview:moviePlayerController.view];
MPMoviePlayerController *mp = [moviePlayerController moviePlayer];
mp.controlStyle = MPMovieControlStyleDefault;
[mp prepareToPlay];
[[moviePlayerController moviePlayer] play];

I am getting error "The operation couldn't be completed. (MediaPlayerErrorDomain error -1013.)", errorLog in NULL, just like accessLog too.

I am using a apache server with AuthType Basic, credentials are right, tested them on web browser. There are no problems with playback if authentification is disabled.

Please help, I can't find what is wrong.

bmajz
  • 129
  • 11
Moze
  • 333
  • 2
  • 15
  • 1
    It's entirely possible that the movie player doesn't consult URL credential storage, because it's not using the URL loading system internally :( – Mike Abdullah Jul 06 '12 at 12:41
  • So is there any other way to play media from url that requires authentication? – Moze Aug 16 '12 at 06:59
  • I would love to know if you came up with anything on this. I agree with Mike Abdullah about not using the credentials you are setting. I am seeing the same thing. I also have the problem that once I set the credentials successfully I can't delete them. None of the solutions I have found have helped. – SteveB Jan 30 '13 at 02:05
  • I ended up with different approach - generating temporary, open links, that would allow only certain amount of connections. – Moze Mar 21 '13 at 14:35

1 Answers1

0

I couldn't get MPMoviePlayerController to do the authentication challenge properly, even thought the Apple docs say otherwise. The VERY hacky solution I came up with was to use Apple's CustomHTTPProtocol to intercept the response and provide the authentication challenge response. I believe the original purpose for this protocol was to handle authentication for UIWebViews.

Link to CustomHTTPProtocol: https://developer.apple.com/library/ios/samplecode/CustomHTTPProtocol/Listings/Read_Me_About_CustomHTTPProtocol_txt.html

My interface declaration:

@interface SampleViewController() <CustomHTTPProtocolDelegate>

Instantiation of MPMoviePlayerController within my SampleViewController:

NSString *fullURLString = @"http://www.samplesite.com/samplemovie.mp4";
NSURL *fullURL = [NSURL URLWithString:fullURLString];

[CustomHTTPProtocol setDelegate:self];
[CustomHTTPProtocol start];

NSURLCredential *credential = [[NSURLCredential alloc]
                              initWithUser:@"username"
                              password:@"password"
                              persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
                                        initWithHost:fullURL.host
                                        port:80
                                        protocol:fullURL.scheme
                                        realm:@"your-realm"
                                        authenticationMethod:NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];

self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:fullURL];
[self.moviePlayer prepareToPlay];
[self.moviePlayer setShouldAutoplay:NO];
[self.moviePlayer setControlStyle:MPMovieControlStyleEmbedded];
[self.moviePlayer.view setFrame:self.sampleView.bounds];
[self.moviePlayer.backgroundView setBackgroundColor:[UIColor colorWithWhite:0.9 alpha:1.0]];
[self.moviePlayer.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[self.sampleView addSubview:self.moviePlayer.view];

Also in my SampleViewController, I have a couple delegate methods. For basic authentication, it's pretty simple:

- (BOOL)customHTTPProtocol:(CustomHTTPProtocol *)protocol canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    BOOL canAuth = ([[protectionSpace authenticationMethod] isEqual:NSURLAuthenticationMethodHTTPBasic] &&
                    [[protectionSpace realm] isEqualToString:@"your-realm"]);
    return canAuth;
}

- (void)customHTTPProtocol:(CustomHTTPProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSURLCredential *newCredential = [NSURLCredential credentialWithUser:@"username"
                                               password:@"password"
                                            persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}

After you call start, all http and https requests go through the CustomHTTPProtocol module

I didn't include CustomHTTPProtocol since Apple provides the source and it's really long. I made some changes to make it work with ARC but it's mostly the same code.

Hopefully this works for you.