我正在創建一個允許用戶與安全服務器進行交互的iPhone應用程序。但是,要驗證用戶,應用程序需要通過SAML從用戶登錄到服務器的數據所在的服務器(提供SSO)。因此,該應用程序模仿發送SAML HTTP請求(通常瀏覽器會照顧)。如何使用NSURLConnection發佈SAML響應消息?
該過程使用Mechanize gem與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
(…)
請注意t他在原始迴應中的標誌被改爲空格。
這似乎是服務器解碼接收到的響應,因此用空格替換+符號的正常行爲:但是,爲什麼當SAML表單從瀏覽器發佈,而不是從NSURLConnection發佈時,它工作?使用不同的編碼來解碼和編碼SAML響應
:
爲了解決我嘗試。現在,使用NSUTF8StringEncoding,也嘗試:NSASCIIStringEncoding,NSNEXTSTEPStringEncoding,NSNonLossyASCIIStringEncoding,NSUnicodeStringEncoding
使用stringByAddingPercentEscapesUsingEncoding,所以這行代碼:
的NSString * samlResponseString = [身體substringWithRange:範圍];
變爲:
NSString* samlResponseString = [[body substringWithRange:range] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- 使用其他enctypes的形式,但服務器甚至不會接受這些要求: 的multipart/form-data的 text/plain的
我非常感謝你的幫助。先謝謝你!