2018-02-28 17:37:31 zhuo212 阅读数 797

前言

前端时间进行报文加密传输改造,碰到了特殊字符和中文乱码问题,后来使用URL编码成功解决(报文传送之前进行URL编码,收到报文之后进行URL解码),记录下,方便以后查看

遇到的问题

  • 解码服务端返回报文是,空格解析成了加号
    • 引起原因
      java中URL编码和iOS中URL编码规范遵循规范不一样(历史原因导致),具体各自遵循什么规范忘记了,也找不到当时是从那看到的了,PS:记住教训,以后看到要及时做好记录
    • 解决方案
      在解码之前手动把“+”替换为“%20”(暂未找到更好的解决方案)
      百度了下,网上也基本都是替换解决的,如:https://www.sojson.com/blog/6.html
    • 疑问:报文中真的有“+”怎么办?
      “+”在进行URL编码时会被处理成“%2B”,所以不用担心报文中真正的“+”被替换成空格,一般情况下空格在URL编码之后会被处理成“%20”

编码实现

说明:编码实现写在字符串分类(category)中

url编码
#pragma mark - URLEncode(URL编码)
/**
 URLEncode(URL编码)

 @return URLEncodeString
 */
- (NSString *)ido_URLEncodedString {
    return [self ido_URLEncodedStringUsingEncoding:NSUTF8StringEncoding];
}

/**
 URLEncode(URL编码)

 @param encoding encoding格式
 @return URLEncodeString
 */
- (NSString *)ido_URLEncodedStringUsingEncoding:(NSStringEncoding)encoding {
    NSString *decodedString = self;

    //NSString *encodedString = [decodedString stringByAddingPercentEscapesUsingEncoding:encoding];
    NSString *encodedString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)decodedString, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", CFStringConvertNSStringEncodingToEncoding(encoding));

    return encodedString;
}
url解码
#pragma mark - URLDecode(URL解码)
/**
 URLDecode(URL解码)

 @return URLDecodeString
 */
- (NSString *)ido_URLDecodedString {
    return [self ido_URLDecodedStringUsingEncoding:NSUTF8StringEncoding];
}

/**
 URLDecode(URL解码)

 @param encoding encoding格式
 @return URLDecodeString
 */
- (NSString *)ido_URLDecodedStringUsingEncoding:(NSStringEncoding)encoding {
    NSString *encodedString = self;
    // 处理iOS环境下 " " 被转换为 "+" 问题
    encodedString = [encodedString stringByReplacingOccurrencesOfString:@"+" withString:@"%20"];

    //NSString *decodedString = [encodedString stringByReplacingPercentEscapesUsingEncoding:encoding];
    NSString *decodedString  = (__bridge_transfer NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (__bridge CFStringRef)encodedString, CFSTR(""), CFStringConvertNSStringEncodingToEncoding(encoding));

    return decodedString;
}
2016-06-29 18:05:21 Ashimar_a 阅读数 659

url编码是一种浏览器用来打包表单输入的格式。浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送的字符,将数据排行等等)作为URL的一部分或者分离地发给服务器。

1.Url编码
iOS中http请求遇到汉字的时候,需要转化为UTF-8,用到的方法是

    NSString *urlStr = @"你好";
    NSString *encodingString = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSLog(@"url编码 = %@",encodingString);

2.Url解码
请求返回的数据,如何像是的是这样的格式%3A%2F%2F,此时我们需要进行UTF-8解码,用到的方法是:

    urlStr = [encodingString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"url解码 = %@",urlStr);
2017-03-08 16:05:27 GorLong 阅读数 1466

       在iOS开发的过程中,我们在网络请求以及加载webView的时候都会用到URL, 众所周知如果URL会含有中文会识别不了,这样我们就要对URL进行编码!

     苹果给我们提供的方法,也是我们经常用的方法是:stringByAddingPercentEscapesUsingEncoding

    

    
    NSString *url = @"http://njkh.g.test.guha-inc.com/434?city=上海";
    url =  [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    ok,这样处理一下我们用url去做网络请求是可以成功的! 但是如果在url中加一些特殊的符号比如  /?#[]@!$&’()*+,;=

   再用stringByAddingPercentEscapesUsingEncoding: 来编码url请求就没办法成功!


     原因:stringByAddingPercentEscapesUsingEncoding没用对特殊符号进行编码处理;

     解决方法: 用CFURLCreateStringByAddingPercentEscapes来对URL进行编码,

- (id)urlEncoded {
  CFStringRef cfUrlEncodedString = CFURLCreateStringByAddingPercentEscapes(NULL,
                                            (CFStringRef)self,NULL,
                                            (CFStringRef)@"!#$%&'()*+,/:;=?@[]",
                                            kCFStringEncodingUTF8);

  NSString *urlEncoded = [NSString stringWithString:(NSString *)cfUrlEncodedString];
  CFRelease(cfUrlEncodedString);
  return urlEncoded;
}

  这样就可以对特殊符号 /?#[]@!$&’()*+,;=进行编码了!

  建议: 对URL编码直接用第二中方法,并把第二种方法写到NSString的分类里面以便使用!



2016-11-27 22:47:41 andanlan 阅读数 12195

前言

在iOS程序中,访问一些HTTP/HTTPS的资源服务时,如果url中存在中文或者特殊字符时,会导致无法正常的访问到资源或服务,想要解决这个问题,需要对url进行编码。

一、编码的原因和范围

1. 为什么要编码

网络标准RFC 1738规定url中只能包含英文字母和阿拉伯数字,以及一些特殊字符:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

“只有字母和数字[0-9a-zA-Z]、和特殊符号”$-_.+!*’(),"[不包括双引号]、及某些保留字,才可以不经过编码直接用于URL。"

此时如果url中包含如汉字或者其他特殊字符则需要对它进行编码,编码的意义在于,假如url的参数中的中文或特殊字符在发送到服务端时,服务端无法解析它的真正意义,会导致服务端不能理解客户端的请求。

如:
url中的保留字?表示后面连接的是一些请求参数,而参数中如果也包含?,服务端就不知道从哪个?之后是参数;
url中的保留字&用来连接并列的参数项,参数中包含&时,服务端依然无法判断。

2. 转码范围

  • ASCII 的控制字符

    这些字符都是不可打印的,自然需要进行转化。

  • 一些非ASCII字符

    这些字符自然是非法的字符范围。转化也是理所当然的了。

  • 一些保留字符

    很明显最常见的就是“&”了,这个如果出现在url中了,那你认为是url中的一个字符呢,还是特殊的参数分割用的呢?

  • 就是一些不安全的字符了。

    例如:空格。为了防止引起歧义,需要被转化为“+”。

二、编码实现

1. 使用CoreFoundationurl参数进行encode

使用到的API

CFStringRef CFURLCreateStringByAddingPercentEscapes(CFAllocatorRef allocator, CFStringRef originalString, CFStringRef charactersToLeaveUnescaped, CFStringRef legalURLCharactersToBeEscaped, CFStringEncoding encoding)

代码示例:

- (void)encodeUrl {
    // p1=%+&sd
    NSString *para1 = [self encodeParameter:@"%+&sd"];
    // p2=我是参数2
    NSString *para2 = [self encodeParameter:@"我是参数2"];
    NSString *encodeUrl = [NSString stringWithFormat:@"https://www.xingshulin.com?p1=%@&p2=%@", para1, para2];
    NSLog(@"%@", encodeUrl);
}

- (NSString *)encodeParameter:(NSString *)originalPara {
    CFStringRef encodeParaCf = CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)originalPara, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8);
    NSString *encodePara = (__bridge NSString *)(encodeParaCf);
    CFRelease(encodeParaCf);
    return encodePara;
}

编码结果:

https://www.xingshulin.com?p1=%25%2B%26sd&p2=%E6%88%91%E6%98%AF%E5%8F%82%E6%95%B02

可以看到转码对象中,除了中文正常转码外,特殊字符只要包含在!*'();:@&=+$,/?%#[]这些字符范围内的都进行了转码。

注意:

此方法适用于,url前缀不包含中文以及其它非法字符的情况,只需要对参数进行编码即可。

2. 使用Foundation框架对完整url进行encode

  • 方法1:(不推荐)

使用到的API

- (nullable NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)enc

代码示例:

NSString *originalUrl = @"https://www.xingshulin.com我是中文?p1=abc&p2=我是参数2";
NSString *encodeUrl = [originalUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", encodeUrl);

编码结果:

https://www.xingshulin.com%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87?p1=abc&p2=%E6%88%91%E6%98%AF%E5%8F%82%E6%95%B02

可以看到转码对象中,除了中文正常转码外,特殊字符只要包含在!*'();:@&=+$,/?%#[]这些字符范围内的都进行了转码。

注意:

此方法适用于url或者参数中包含中文以及其它非法字符的情况,但不适用于参数包含保留字和其他特殊字符的情况。

  • 方法2:(推荐)

使用到的API

- (nullable NSString *)stringByAddingPercentEncodingWithAllowedCharacters:(NSCharacterSet *)allowedCharacters

代码示例:

NSString *originalUrl = @"https://www.xingshulin.com我是中文?p1=abc&p2=我是参数2";
NSCharacterSet *encodeUrlSet = [NSCharacterSet URLQueryAllowedCharacterSet];
NSString *encodeUrl = [originalUrl stringByAddingPercentEncodingWithAllowedCharacters:encodeUrlSet];
NSLog(@"%@", encodeUrl);

编码结果:

https://www.xingshulin.com%E6%88%91%E6%98%AF%E4%B8%AD%E6%96%87?p1=abc&p2=%E6%88%91%E6%98%AF%E5%8F%82%E6%95%B02

可以看到转码对象中,除了中文正常转码外,特殊字符只要包含在!*'();:@&=+$,/?%#[]这些字符范围内的都进行了转码。

注意:

与方法1相同。

  • 对比

之所以推荐方法2,是由于方法1已经在iOS9中被苹果废弃,而且1支持的字符比较少,只对 #%^{}[]|\"<> 加空格 共14个字符编码,不包括 &? 等符号。

三、拓展——stringByAddingPercentEncodingWithAllowedCharacters用法

stringByAddingPercentEncodingWithAllowedCharacters接收NSCharacterSet对象,几种常用的NSCharacterSet

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}

URLHostAllowedCharacterSet      "#%/<>?@\^`{|}

URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}

URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}

URLQueryAllowedCharacterSet    "#%<>[\]^`{|}

URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

四、参考

rfc1738

关于URL编码

为什么要对url进行encode

url出现特殊字符处理-- stringByAddingPercentEncodingWithAllowedCharacters

NSCharacterSet

2016-03-15 10:41:26 jerryjqq 阅读数 554

iOS url中文编码

前几天碰到个问题,就是在搜索股票时,需要支持股票名检索的支持,那时候我的做法是直接将中文放到url中,这时候会出现url为nil,然后出现app的奔溃。后来想到应该是需要对中文进行编码,然后问题就解决了。编码方式如下:

[urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

ps:百度来的api已经被apple给pass掉了,所以建议google。

苹果官方对这个问题的解释如下:

The URL string with which to initialize the NSURL object. This URL string must conform to URL format as described in RFC 2396, and must not be nil. This method parses URLString according to RFCs 1738 and 1808.

URL编码

阅读数 416

没有更多推荐了,返回首页