问题描述
我必须使用我的Web服务器登录,但一切正常,但不能生成|%<> {}¥^〜之类的密码.我该如何编码这样的密码?
I have to login with my to a web-server.All works fine, but not generated passwords like |%<">{}¥^~ . How I have to encode passwords like this?
我用密码= |%<> {}¥^〜创建一个用户胶印工作(例如,像"user1234"这样的密码可以正常工作)
I create a User with password=|%<">{}¥^~doset work( for example a password like "user1234" works fine)
NSString *userName = self.usernameOutlet.text;
NSString *userPassword = self.passwordOutlet.text;
NSString *escapedString = [self.passwordOutlet.text stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
userPassword = escapedString;
NSString *post = [NSString stringWithFormat:@"login=%@&password=%@",userName,userPassword];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"http://XXXXXXXX/login"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
使用"user1234"之类的密码,我得到一个cookie
with passwords like "user1234" I get a cookie
使用"|%<> {}¥^〜"之类的密码,我没有得到cookie
with passwords like "|%<">{}¥^~" I get no cookie
我在做什么错了?
推荐答案
想使用URLQueryAllowedCharacterSet
很诱人,但这并不适用于所有字符串.显然&
和+
将不转义通过.
It’s tempting to want to use URLQueryAllowedCharacterSet
, but that won’t work for all strings. Notably &
and +
will pass unescaped.
如果您想知道为什么我们也必须对&
和+
进行百分比转义,这是因为这两个字符在x-www-form-urlencoded
请求中具有特殊含义. &
用于在x-www-form-urlencoded
请求中定界键值对,因此它将截断您的密码.而且大多数网络服务都将+
转换为空格,因此您也希望将其转义.
If you’re wondering why we must percent escape &
and +
, too, it’s because these two characters have a special meaning in x-www-form-urlencoded
requests. The &
is used to delimit key-value pairs in a x-www-form-urlencoded
request, so it will truncate your password. And most web services translate a +
to a space, so you’ll want to percent escape that, too.
因此,我们首先定义一个可以使用的字符集:
So, let’s first define a character set that will work:
// NSCharacterSet+URLQueryValueAllowed.h
@interface NSCharacterSet (URLQueryValueAllowed)
@property (class, readonly, copy) NSCharacterSet *URLQueryValueAllowedCharacterSet;
@end
和
// NSCharacterSet+URLQueryValueAllowed.m
@implementation NSCharacterSet (URLQueryValueAllowed)
+ (NSCharacterSet *)URLQueryValueAllowedCharacterSet {
static dispatch_once_t onceToken;
static NSCharacterSet *queryValueAllowed;
dispatch_once(&onceToken, ^{
NSMutableCharacterSet *allowed = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
NSString *generalDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
NSString *subDelimitersToEncode = @"!$&'()*+,;=";
[allowed removeCharactersInString:generalDelimitersToEncode];
[allowed removeCharactersInString:subDelimitersToEncode];
queryValueAllowed = [allowed copy];
});
return queryValueAllowed;
}
@end
然后,为了让我们更轻松,让我们定义NSDictionary
类别以对字典进行百分比编码:
Then, to make life easier for us, let’s define NSDictionary
category for percent encoding a dictionary:
// NSDictionary+PercentEncoded.h
@interface NSDictionary (PercentEncoded)
- (NSString *)percentEncodedString;
- (NSData *)percentEncodedData;
@end
和
// NSDictionary+PercentEncoded.m
@implementation NSDictionary (PercentEncoded)
- (NSString *)percentEncodedString {
NSMutableArray<NSString *> *results = [NSMutableArray array];
NSCharacterSet *allowed = [NSCharacterSet URLQueryValueAllowedCharacterSet];
for (NSString *key in self.allKeys) {
NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:allowed];
NSString *value = [[self objectForKey:key] description];
NSString *encodedValue = [value stringByAddingPercentEncodingWithAllowedCharacters:allowed];
[results addObject:[NSString stringWithFormat:@"%@=%@", encodedKey, encodedValue]];
}
return [results componentsJoinedByString:@"&"];
}
- (NSData *)percentEncodedData {
return [[self percentEncodedString] dataUsingEncoding:NSUTF8StringEncoding];
}
@end
然后,您的应用程序代码可以执行以下操作:
Then, your application code can do:
NSDictionary *dictionary = @{@"login": userName, @"password": userPassword};
NSData *body = [dictionary percentEncodedData];
这篇关于如何通过NSURLConnection将带有特殊字符的密码从应用程序提交到Web服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!