2015-04-22 16 views
12

Tôi đang cố gắng truyền các chuỗi được mã hóa dài qua mạng và khiến chúng xuất hiện chính xác trên máy chủ. Ví dụ, tôi có chuỗi mã hóa này trên máy khách:NSCharacterSet URLHostAllowedCharacterSet không thay thế dấu '+'?

wcWSERZCh8Xm1hpbNo1kSD1LvFmpuUr4wmq9hQUWeK0vYcLeFPGwFR/sBTES1A4rPV6eyp9nzEEU9uKkiFSTdP + SPOSqUf6evjf3WRHrXMRe81lIrHuRyk0iRwoNe5uIk + VlpR41kETmznXa4 + gELmf53r7oayRkkffnIPDmpO + WbgE0VL3PQeOsXB01tWJyDiBIsz5WJiiEIm3ZoJW/sw ==

Như bạn thấy, nó có một vài ký tự sẽ không truyền qua mạng mà không có mã hóa URL nào đó (+/, đáng chú ý nhất). Tôi không hoàn toàn chắc chắn nếu có thể có các nhân vật khác có thể phát sinh trong các tình huống khác, vì vậy tôi muốn đảm bảo rằng giải pháp của tôi là 'phổ quát' chính xác. Tôi đang sử dụng dòng này:

NSString *escapedString = [cipherString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; 

mà tôi tìm thấy trong đánh giá cao answer.

Tuy nhiên, tôi vẫn gặp khó khăn trong việc giải mã này ở phía máy chủ, vì vậy tôi in ra kết quả trên máy khách ngay lập tức trước khi gửi, và tôi thấy điều này:

wcWSERZCh8Xm1hpbNo1kSD1LvFmpuUr4wmq9hQUWeK0vYcLeFPGwFR% 2FsBTES1A4rPV6eyp9nzEEU9uKkiFSTdP + SPOSqUf6evjf3WRHrXMRe81lIrHuRyk0iRwoNe5uIk + VlpR41kETmznXa4 + gELmf53r7oayRkkffnIPDmpO + WbgE0VL3PQeOsXB01tWJyDiBIsz5WJiiEIm3ZoJW% 2Fsw ==

Tại sao các '+' dấu hiệu vẫn còn? Tôi có sử dụng sai ký tự được cho phép không? Tôi nên sử dụng bộ ký tự nào để đảm bảo rằng tôi đã thoát đúng tất cả các ký tự có vấn đề?

Nếu được, đây là mã tôi đang sử dụng để mã hóa chuỗi văn bản thuần túy. Khi nó được thực hiện, tôi base64 mã hóa các kết quả trước khi gửi qua mạng:

- (NSData *)phpEncryptCleartext : (NSData *)cleartext 
{ 
    NSData *cleartextPadded = [self phpPadData:cleartext]; 

    CCCryptorStatus ccStatus  = kCCSuccess; 
    size_t   cryptBytes  = 0; // Number of bytes moved to buffer. 
    NSMutableData *cipherTextData = [NSMutableData dataWithLength:cleartextPadded.length]; 

    ccStatus = CCCrypt(kCCEncrypt, 
         kCCAlgorithmAES128, 
         0, 
         _sessionKey.bytes, 
         kCCKeySizeAES128, 
         _iv.bytes, 
         cleartextPadded.bytes, 
         cleartextPadded.length, 
         cipherTextData.mutableBytes, 
         cipherTextData.length, 
         &cryptBytes); 

    if (ccStatus == kCCSuccess) { 
     cipherTextData.length = cryptBytes; 
    } 
    else { 
     NSLog(@"kEncryptionError code: %d", ccStatus); // Add error handling 
     cipherTextData = nil; 
    } 

    return cipherTextData; 
} 

Cảm ơn lời khuyên nào!

+0

tôi đã không kiểm tra docu nhưng nếu nếu không thoát khỏi '+' (mà từ POV của tôi sẽ là ok), bạn có thể bắn lên của bạn thay thế chuỗi riêng thay đổi cộng với biểu tượng dấu và ký hiệu tương đương. –

+0

Có lẽ bạn nên thử 'URLFragmentAllowedCharacterSet'? –

+0

'URLFragmentAllowedCharacterSet' đã tạo ra các sự cố khác. Tôi có thể dễ dàng thay thế dây chuyền của riêng mình, nhưng tôi lo ngại về việc dập tắt đám cháy khi chúng phát sinh, vì vậy tôi không thể hoàn toàn tự tin rằng tôi đã thấy tất cả các nhân vật có vấn đề. Tôi giả định rằng điều này đã được xử lý nhiều lần trước đây, và tôi hy vọng rằng có một phương pháp được xây dựng trong đó sẽ xử lý nó một cách đáng tin cậy. Bây giờ, mặc dù, tôi có lẽ sẽ phải xử lý nó như bạn đề nghị. Cảm ơn! – Alex

Trả lời

27

Phiên bản Swift here.

Để thoát khỏi sử dụng nhân vật stringByAddingPercentEncodingWithAllowedCharacters:

NSString *URLEscapedString = 
[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; 

Sau đây là các bộ ký tự bổ ích, thực sự là nhân vật không có trong bộ:

URLFragmentAllowedCharacterSet "#%<>[\]^`{|} 
URLHostAllowedCharacterSet  "#%/<>[email protected]\^`{|} 
URLPasswordAllowedCharacterSet "#%/:<>[email protected][\]^`{|} 
URLPathAllowedCharacterSet  "#%;<>?[\]^`{|} 
URLQueryAllowedCharacterSet  "#%<>[\]^`{|} 
URLUserAllowedCharacterSet  "#%/:<>[email protected][\]^` 

Hoặc tạo characterset riêng của bạn chỉ với nhân vật bạn cần phải trốn thoát.

NSCharacterSet *customCharacterset = [[NSCharacterSet characterSetWithCharactersInString:@"your characters"] invertedSet]; 

Tạo một characterset kết hợp tất cả những điều trên:

NSCharacterSet *URLFullCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>[email protected][\\]^`{|}"] invertedSet]; 

Tạo một Base64

Trong trường hợp của Base64 characterset:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet]; 

Lưu ý: stringByAddingPercentEncodingWithAllowedCharacters cũng sẽ mã hóa Các ký tự UTF-8 yêu cầu mã hóa.

Ví dụ để xác minh các nhân vật trong bộ:

void characterInSet(NSCharacterSet *set) { 
    NSMutableString *characters = [NSMutableString new]; 
    NSCharacterSet *invertedSet = set.invertedSet; 
    for (int i=32; i<127; i++) { 
     if ([invertedSet characterIsMember:(unichar)i]) { 
      NSString *c = [[NSString alloc] initWithBytes:&i length:1 encoding:NSUTF8StringEncoding]; 
      [characters appendString:c]; 
     } 
    } 
    printf("characters not in set: '%s'\n", [characters UTF8String]); 
} 
+0

Đã cập nhật câu trả lời. – zaph

+0

Cảm ơn bạn rất nhiều! – Alex

+1

Câu trả lời tuyệt vời là bây giờ chúng ta phải mã hóa từng phần của URL một cách khác nhau, hoặc là có một kích thước phù hợp với tất cả các phương pháp tiếp cận? Ngoài ra, làm cách nào bạn xác định chính xác những ký tự mà mỗi bộ ký tự được bao gồm? Các tài liệu táo không mở rộng và luôn mơ hồ. Cảm ơn – RyanTCB

Các vấn đề liên quan