2012-03-29 13 views
5

私は、ユーザーがセキュリティで保護されたサーバーと対話できるようにするiPhoneアプリを作成しています。ただし、ユーザーを認証するには、ユーザーがデータを取得しているサーバー(SSOを提供しているサーバー)にログインするサーバーからSAMLを経由する必要があります。したがって、アプリケーションはSAML HTTPリクエストの送信を模倣しています(通常はブラウザが処理します)。NSURLConnectionを使用してSAML応答メッセージを投稿するにはどうすればよいですか?

このプロセスはMechanize宝石を使ってRubyで作業していますが、今はNSURLConnectionでiPhoneで動作させることができません。

私が遭遇する問題は、base64でエンコードされたSAMLレスポンスがNSURLConnectionによってサーバーに正しく送信されないようです。 +記号はスペースで置き換えられ、サーバー側のSAML応答のデコードに失敗します。 stringByAddingPercentEscapesUsingEncodingでURLエンコーディングを使用すると、同じデコードエラーが発生します。

これはコードSAMLレスポンスを抽出し、送信している:

// Extract the SAML Response from the form that is sent by the server 
body = [[NSString alloc] initWithData:[self receivedData]  encoding:NSUTF8StringEncoding]; 
NSString *searchSAMLResponseStart = @"name=\"SAMLResponse\" value=\""; 
NSString *searchSAMLResponseEnd = @">\n<NOSCRIPT><INPUT TYPE=\"SUBMIT\""; 
NSRange samlResponseStartRange = [body rangeOfString:searchSAMLResponseStart options:0]; 
NSRange samlResponseEndRange = [body rangeOfString:searchSAMLResponseEnd options:0]; 
NSRange range = NSMakeRange (NSMaxRange(samlResponseStartRange), samlResponseEndRange.location - NSMaxRange(samlResponseStartRange) -1); 
NSString* samlResponseString = [body substringWithRange:range]; 

// Construct the SAML POST request 
NSURL    *url; 
NSMutableURLRequest *request; 
url = [NSURL URLWithString:kSamlPostUrl]; 
request = [NSMutableURLRequest requestWithURL:url]; 
NSString *userAgent = kUserAgent; 
[request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; 
[request setHTTPMethod:@"POST"]; 
NSString *post = [@"RelayState=https://example.com&SAMLResponse=" stringByAppendingString:samlResponseString]; 
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]; 
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]]; 
[request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
[request setHTTPBody:postData]; 

// Send the request   
self.connectionPostSaml = [NSURLConnection connectionWithRequest:request delegate:self]; 

サーバが送信し、SAMLレスポンスがから取られる場合、このようになっていることをSAML形式:

<html> 
<HEAD><META HTTP-EQUIV='PRAGMA' CONTENT='NO-CACHE'><META HTTP-EQUIV='CACHE-CONTROL'  CONTENT='NO-CACHE'><TITLE>SAML 2.0 Auto-POST form</TITLE></HEAD> 
    <body onLoad="document.forms[0].submit()"> 
<NOSCRIPT>Your browser does not support JavaScript. Please click the 'Continue' button  below to proceed. <br><br></NOSCRIPT> 
     <form action="https://sso.example.com/saml2" method="POST"> 
     <input type="hidden" name="RelayState" value="https://example.com"> 
     <input type="hidden" name="SAMLResponse"  value="PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERl 
c3RpbmF0aW9uPSJodHRwczovL3Nzby5vcG93ZXIuY29tL3NwL0FDUy5zYW1sMiIgSUQ9Il85ZWY0 
M2MzMGRkZmQ0YzY1ODNiMjgxZjAwNDU5ZWQyMjZmMjQiIElzc3VlSW5zdGFudD0iMjAxMi0wMy0y 
OFQyMTo0MDowNloiIFZlcnNpb249IjIuMCI+CiAgICA8bnMxOklzc3VlciB4bWxuczpuczE9InVy 
bjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5h 
bWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5wZ2UuY29tPC9uczE6SXNzdWVy 
(…) 
cnRpb24+CjwvUmVzcG9uc2U+"> 
<NOSCRIPT><INPUT TYPE="SUBMIT" VALUE="Continue"></NOSCRIPT> 
     </form> 
    </body> 
</html> 

そして、 POST要求を受信した後にサーバーが生成するエラー:

Unable to parse incoming SAML2 message, raw:  PFJlc3BvbnNlIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERl 
c3RpbmF0aW9uPSJodHRwczovL3Nzby5vcG93ZXIuY29tL3NwL0FDUy5zYW1sMiIgSUQ9Il9iN2Q5 
OTZhMmI1MjhiNWRkNjY0YWM4YjUwZmVjM2M2OTMzMWEiIElzc3VlSW5zdGFudD0iMjAxMi0wMy0y 
OVQyMjowMzoxNVoiIFZlcnNpb249IjIuMCI CiAgICA8bnMxOklzc3VlciB4bWxuczpuczE9InVy 
bjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5h 
bWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5wZ2UuY29tPC9uczE6SXNzdWVy 
PgogICAgPFN0YXR1cz4KICAgICAgICA8U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVz 
OnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8 CiAgICA8L1N0YXR1cz4KICAgIDxuczI6QXNz 
(…) 

彼と生の応答のサインはスペースに変わります。

受信したレスポンスをデコードしてスペースを空白記号に置き換えるのは正常な動作です:SAMLフォームがブラウザからポストされていてもNSURLConnectionからポストされていないと、なぜ動作しますか?

  • SAML応答を復号し、符号化するために異なる符号化を使用して:私は試み解決するために

    。今NSUTF8StringEncodingを使用しても試みた:NSASCIIStringEncoding、NSNEXTSTEPStringEncoding、NSNonLossyASCIIStringEncoding、NSUnicodeStringEncoding stringByAddingPercentEscapesUsingEncodingを用い

  • ので、このコード行:

    NSStringの* samlResponseString = [本体substringWithRange:範囲]。

    フォームの他のenctypesを使用して
    NSString* samlResponseString = [[body substringWithRange:range] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
    
    • が、サーバーでも、これらの要求を受け入れないだろう:

    はなり マルチパート/フォームデータを text/plainの

私はあなたの助けに大変感謝します。前もって感謝します!

答えて

0

投稿からbase64を送信する際に問題が発生し、URLエンコードで解決しました。試してみてください:

NSString *post = [@"RelayState=https://example.com&SAMLResponse=" stringByAppendingString: 
     (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, 
     (__bridge CFStringRef)samlResponseString, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", 
     CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding))]; 
関連する問題