NSData不会接受有效的base64编码的string

我正在iOS(7)cient端实施JSON Web令牌authentication。 这工作很好。 我的应用程序获得令牌,并可以与他们进行身份validation的调用我的服务器。

现在,我希望我的客户端代码检查令牌的到期date,以便知道何时重新进行身份validation。 检查JWT授权令牌上的到期date很简单。 授权令牌是3个base64编码的JSON blob,由'。'分隔。 – 到期时间戳在中间的blob中,在一个叫做ext的字段中。 从Unix时代开始秒。

所以我的代码看起来像这样:

 - (NSDate*) expirationDate { if ( !_tokenAppearsValid ) return nil; if ( !_parsedExpirationDate ) { // // Token is three base64 encoded payloads separated by '.' // The payload we want is the middle one, which is a JSON dict, with // 'exp' being the unix seconds timestamp of the expiration date // Returning nil is appropriate if no 'exp' is findable // NSArray *components = [self.token componentsSeparatedByString:@"."]; NSString *payload = components[1]; NSData* payloadJsonData = [[NSData alloc] initWithBase64EncodedString:payload options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSError* jsonError = nil; NSDictionary* payloadJson = [NSJSONSerialization JSONObjectWithData:payloadJsonData options:0 error:&jsonError]; if ( payloadJson ) { if ( payloadJson[@"exp"] ) { NSTimeInterval timestampSeconds = [payloadJson[@"exp"] doubleValue]; _expirationDate = [NSDate dateWithTimeIntervalSince1970:timestampSeconds]; } } _parsedExpirationDate = YES; } return _expirationDate; } 

问题很简单。 当用NSData -initWithBase64EncodedStringparsing时,中间的base64 blob是nil – 这很糟糕。

我已经检查了base64 blob,它似乎是有效的。 我的服务器暂时返回虚拟数据,所以这里是一个示例blob: eyJlbWFpbCI6ImZvb0BiYXIuYmF6IiwiYWNjb3VudElkIjoiMTIzNDUtNjc4OTAtYmFyLWJheiIsImV4cCI6MTM5MDkxNTAzNywiaWF0IjoxMzkwOTE0MTM3fQ

它解码为:

 {"email":"foo@bar.baz","accountId":"12345-67890-bar-baz","exp":1390915037,"iat":1390914137} 

我在这里testing它: http : //www.base64decode.org

我使用NSData的base64方法在我的应用程序成功的地方 – 我不认为我在这里做任何特别打破。 但我都是耳朵! 有任何想法吗?

您的Base64string无效。 它必须填充=字符长度是4的倍数。在你的情况下: "eyJlbWFp....MTM3fQ=="

使用此填充, initWithBase64EncodedString正确解码Base64string。

虽然马丁的答案是正确的,但这是解决问题的一种快速而正确的方法:

 NSString *base64String = @"<the token>"; NSUInteger paddedLength = base64String.length + (4 - (base64String.length % 4)); NSString* correctBase64String = [base64String stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0]; 

下面是一个解决scheme,适当填充Base-64string,并在iOS 4 +中工作:

的NSData + Base64.h

 @interface NSData (Base64) /** Returns a data object initialized with the given Base-64 encoded string. @param base64String A Base-64 encoded NSString @returns A data object built by Base-64 decoding the provided string. Returns nil if the data object could not be decoded. */ - (instancetype) initWithBase64EncodedString:(NSString *)base64String; /** Create a Base-64 encoded NSString from the receiver's contents @returns A Base-64 encoded NSString */ - (NSString *) base64EncodedString; @end 

的NSData + Base64.m

 @interface NSString (Base64) - (NSString *) stringPaddedForBase64; @end @implementation NSString (Base64) - (NSString *) stringPaddedForBase64 { NSUInteger paddedLength = self.length + (self.length % 3); return [self stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0]; } @end @implementation NSData (Base64) - (instancetype) initWithBase64EncodedString:(NSString *)base64String { return [self initWithBase64Encoding:[base64String stringPaddedForBase64]]; } - (NSString *) base64EncodedString { return [self base64Encoding]; } @end 

保罗答案的一个迅速版本

 func paddedBase64EncodedString(encodedString: String) -> String { let encodedStringLength = encodedString.characters.count let paddedLength = encodedStringLength + (4 - (encodedStringLength % 4)) let paddedBase64String = encodedString.stringByPaddingToLength(paddedLength, withString: "=", startingAtIndex: 0) return paddedBase64String } 

我遇到了同样的问题,但通过在string末尾添加==解决此问题

 base64UserStr = NSString(format: "%@%@", base64UserStr,"==") as String let decodedData = NSData(base64EncodedString: base64UserStr, options: NSDataBase64DecodingOptions.init(rawValue: 0)) if (decodedData != nil) { let decodedString = NSString(data: decodedData!, encoding: NSUTF8StringEncoding) print("Base 64 decode string is \(decodedString)") } 

这一定会工作。

 NSString *base64String = @"<the token>"; NSUInteger paddedLength = base64String.length + ((base64String.length % 4)>0 ? (4 - (base64String.length % 4)): 0); NSString* correctBase64String = [base64String stringByPaddingToLength:paddedLength withString:@"=" startingAtIndex:0]; 

修复了pauls错误,导致base64string在结尾处得到额外的====,如果string不需要填充。 解码基本64string后,这添加了一个额外的字符。 在我的scheme中打破了jsonparsing器。