为了满足安全相关的需求,Apple向开发者提供了Security框架和CommonCrypto接口,可以在应用中使用。
Security框架是一套C API的集合,用于管理证书、信任策略以及对设备安全数据存储的访问。
CommonCrypto是一套接口的集合,用于数据的加解密、生成常见的密码散列(比如MD5和SHA1),计算消息认证码,生成密码或是基于密码的密钥等。
我们将会介绍如何使用Security框架与NSURLConnection来验证客户端与服务器的身份,还会介绍常见的认证模式,并提供一个关于加密传输数据的示例。和解密服务器响应,并使用设备的钥匙串安全的存储认证信息。
验证服务器通信
移动应用没法确保应用到Internet的连接是安全的,不会被其他人窥探。确保用户只与期望的服务器进行通信是开发者的职责。
最佳实践是使用NSURLProtectionSpace验证应用的用户与服务器进行通信。
下面展示如何创建保护空间:
NSURLProtectionSpace *defaultSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"yourbankingdomain.com"
port:443
protocol:NSURLProtectionSpaceHTTPS
realm:@"mobile"
authenticationMethod:NSURLAuthenticationMethodDefault];
既然已经使用服务器的属性创建了保护空间,你需要确保将其用于验证连接。实现willSendRequestForAuthenticationChallenge:可以检查挑战,确定是否想要响应服务器的认证挑战,同事发出恰当的挑战响应。
认证挑战响应是NSURLCredential的实例,可用于创建信任、用户名/密码组合和客户端证书。
-(void)connection:(NSURLConnection *)connection
willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSURLProtectionSpace *defaultSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"yourbankingdomain.com"
port:443
protocol:NSURLProtectionSpaceHTTPS
realm:@"mobilebanking"
authenticationMethod:NSURLAuthenticationMethodDefault];
NSURLProtectionSpace *trustSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"yourbankingdomain.com"
port:443
protocol:NSURLProtectionSpaceHTTPS
realm:@"mobilebanking"
authenticationMethod:NSURLAuthenticationMethodClientCertificate];
NSArray *validSpaces = @[defaultSpace, trustSpace];
if (![validSpaces containsObject:challenge.protectionSpace])
{
NSString *msg = @"We are unable to establish a secure connection. Please check your network conection and try again.";
dispatch_async(dispatch_get_main_queue(), ^
{
});
[challenge.sender cancelAuthenticationChallenge:challenge];
}
}
这种特定的验证会确保应用只与指定的服务器进行通信。如果发现处于恶意网络之上,传输被重新路由到第三方服务器,那么保护控件验证就会因不匹配的主机而失败,后续的通信也会终止。
实现后端灵活性的另一种方式是只验证认证挑战中的某些属性,比如主机、端口与协议是否与预先定义好的相匹配。
if (![challenge.protectionSpace.host isEqualToString:@"yourbankingdomain.com"] ||
challenge.protectionSpace.port != 443 ||
![challenge.protectionSpace.protocol isEqualToString:NSURLProtectionSpaceHTTPS])
{
//提示
[challenge.sender cancelAuthenticationChallenge:challenge];
}
服务器验证是非常重要的,不过尚不足以阻止所有的攻击。要想确保用户数据的安全,还需要仔细评估和考虑其他一些安全度量,比如消息完整性与数据加密等。