4

作成している(Web)アプリケーションの場合、基本認証を使用してUIWebViewにページをロードする必要があります。

次に、使用する認証ヘッダーを設定します。

NSString *result = [NSString stringWithFormat:@"%@:%@", username, password];
NSData *resultData = [result dataUsingEncoding:NSASCIIStringEncoding];

NSString *result64 = [NSString stringWithFormat:@"Basic %@", [resultData base64Encoding]];
[request setValue:result64 forHTTPHeaderField:@"Authorization"];

私のapacheアクセスログでは、ログインが成功していることがわかります。しかし、UIWebViewはのようなリソースをロードしたいのですstyle.cssjquery.min.js、これらのリソースへのリクエストは、Authorizationヘッダーが設定されていないため失敗します。どうすればこれを修正できますか?

4

1 に答える 1

4

解決策は、NSURLProtocolをサブクラス化して、リソースのロードを認証することでした。

#import <Foundation/Foundation.h>

#import "AuthenticationUtils.h"

@interface CustomURLProtocol : NSURLProtocol <NSURLConnectionDelegate>
{
    NSMutableURLRequest *_customRequest;
    NSURLConnection *_connection;
}

@end

@implementation CustomURLProtocol

static NSString *AUTHORIZED_REQUEST_HEADER = @"X-AUTHORIZED";

+(BOOL) canInitWithRequest:(NSMutableURLRequest *)request
{
    // check if the request is one you want to authorize
    BOOL canInit = (![request.URL.scheme isEqualToString:@"file"] && [request valueForHTTPHeaderField:[AUTHORIZED_REQUEST_HEADER stringByAppendingString:[request.URL absoluteString]]] == nil);
    return canInit;
}

-(id) initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client
{        
    _customRequest = [request mutableCopy];
    [_customRequest setValue:@"" forHTTPHeaderField:[AUTHORIZED_REQUEST_HEADER stringByAppendingString:[request.URL absoluteString]]];

    self = [super initWithRequest:_customRequest cachedResponse:cachedResponse client:client];

    return self;
}

+(NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request
{
    NSMutableURLRequest *customRequest = [request mutableCopy];
    [customRequest setValue:@"" forHTTPHeaderField:[AUTHORIZED_REQUEST_HEADER stringByAppendingString:[request.URL absoluteString]]];

    NSString *basicAuthentication = [AuthenticationUtils getBasicAuthentication];
    [customRequest setValue:basicAuthentication forHTTPHeaderField:@"Authorization"];

    return customRequest;
}

- (void) startLoading
{
    NSString *basicAuthentication = [AuthenticationUtils getBasicAuthentication];
    [_customRequest setValue:basicAuthentication forHTTPHeaderField:@"Authorization"];

    _connection = [NSURLConnection connectionWithRequest:_customRequest delegate:self];
}

- (void) stopLoading
{
    [_connection cancel];
}

#pragma mark - NSURLConnectionDelegate

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{
    // This protocol forgets to store cookies, so do it manually
    if([redirectResponse isKindOfClass:[NSHTTPURLResponse class]])
    {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:[NSHTTPCookie cookiesWithResponseHeaderFields:[(NSHTTPURLResponse*)redirectResponse allHeaderFields] forURL:[redirectResponse URL]] forURL:[redirectResponse URL] mainDocumentURL:[request mainDocumentURL]];
    }

    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [[self client] URLProtocol:self didLoadData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    [[self client] URLProtocol:self didFailWithError:error];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection 
{
    [[self client] URLProtocolDidFinishLoading:self];
}

-(NSURLRequest *) connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{    
    // This protocol forgets to store cookies, so do it manually
    if([redirectResponse isKindOfClass:[NSHTTPURLResponse class]])
    {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:[NSHTTPCookie cookiesWithResponseHeaderFields:[(NSHTTPURLResponse*)redirectResponse allHeaderFields] forURL:[redirectResponse URL]] forURL:[redirectResponse URL] mainDocumentURL:[request mainDocumentURL]];
    }

    // copy all headers to the new request
    NSMutableURLRequest *redirect = [request mutableCopy];
    for (NSString *header in [request allHTTPHeaderFields]) 
    {
        [redirect setValue:[[request allHTTPHeaderFields] objectForKey:header] forHTTPHeaderField:header];
    }

    return redirect;
}

@end

そして、AppDelegateにこれを追加します。

[NSURLProtocol registerClass:[CustomURLProtocol class]];
于 2012-05-14T11:35:30.743 に答える