我想使用AES256加密/解密来自NSURLSession
的所有缓存数据。我是使用Alamofire的新手,但我认为可以在不涉及图书馆本身的情况下这样做。
我不确切知道在缓存之前加密数据的最无缝方式是什么,并在从缓存中检索后对其进行解密。
我发现我可以使用Alamofire SessionDelegate
以及方法dataTaskWillCacheResponse
和dataTaskWillCacheResponseWithCompletion
进行加密,但我看不到与从中提取的数据有关的任何内容用于解密的缓存。
另一方面,我考虑使用自定义NSURLProtocol
来覆盖cachedResponse
但我没有看到任何与该响应缓存有关的内容,只有提取的数据。
总之,我不知道是否可以实现这一目标,或者我必须在NSURLSessionDelegate/SessionDelegate
和NSURLProtocol
之间使用混合,或者可能是NSURLCache
的子类做这个工作并把它传递到Alamofire会议,或者有一些更简单的东西,或者我非常错误:P
任何帮助都将非常感激。
我试图通过下一个实现来实现它。首先是缓存的一个非常简单的子类:
class EncryptedURLCache: URLCache {
let encryptionKey: String
init(memoryCapacity: Int, diskCapacity: Int, diskPath path: String? = nil, encryptionKey: String) {
guard !encryptionKey.isEmpty else {
fatalError("No encryption key provided")
}
self.encryptionKey = encryptionKey
super.init(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: path)
}
override func cachedResponse(for request: URLRequest) -> CachedURLResponse? {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
return super.cachedResponse(for: request)?.cloneDecryptingData(withKey: encryptionKey)
}
override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
super.storeCachedResponse(cachedResponse.cloneEncryptingData(withKey: encryptionKey), for: request)
}
}
缓存响应的扩展,以返回加密/解密数据
extension CachedURLResponse {
func cloneEncryptingData(withKey key: String) -> CachedURLResponse {
return clone(withData: data.aes256Encrypted(withKey: key))
}
func cloneDecryptingData(withKey key: String) -> CachedURLResponse {
return clone(withData: data.aes256Decrypted(withKey: key) ?? data)
}
private func clone(withData data: Data) -> CachedURLResponse {
return CachedURLResponse(
response: response,
data: data,
userInfo: userInfo,
storagePolicy: storagePolicy
)
}
}
这是有效的,但仅适用于我使用标题Cache-Control: max-age=60
挂载的mockable.io。我还针对SWAPI http://swapi.co/api/people/1/
和Google图书https://www.googleapis.com/books/v1/volumes?q=swift+programming
进行了测试。
在所有三种情况下,响应都已正确加密和缓存。我正在进行测试,切断互联网连接并设置会话配置requestCachePolicy = .returnCacheDataDontLoad
。
在这种情况下,对mockable.io的请求被正确解密并从缓存中返回,但其他人说NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline."
。这非常奇怪,因为根据该策略,如果无法返回缓存数据,则必须说NSURLErrorDomain Code=-1008 "resource unavailable"
。如果解密时出现错误,则表示序列化为JSON对象时出错。
我还使用公共共享缓存进行了测试,它按预期工作,使用该策略返回数据。我认为这可能与SWAPI和GBooks响应中缺少缓存头有关,但是这个测试有效,它返回缓存的数据。
然后我做了另一个测试:使用我的缓存但没有加密/解密数据,只需按原样克隆返回的缓存响应,没有结果。然后我尝试了最后一个非常愚蠢的测试:为了避免克隆响应,只需返回cachedResponse
然后IT工作。 h ***是如何可能的?如果我克隆cachedResponse以注入我的加密/解密数据,它就不起作用了!即使在examples from Apple中,他们也会毫不畏惧地创建新的缓存响应。
我不知道错误在哪里,但我会在一两分钟内跳过窗户。
请帮忙吗?非常感谢你。
我正在使用Apple的DTS工程师更改电子邮件,结论是这不可能实现这一点,因为支持CF类型比Foundation对象做更多的逻辑,在这种情况下它正在对URLRequest进行验证当系统缓存响应时传递给它,但是当使用常规NSCachedURLResponse进行克隆时我无法传递它。
当系统对请求进行验证时,没有可匹配的。
答案 0 :(得分:3)
没有办法拦截我所知道的委托方的缓存检索调用,而且我不认为甚至会要求自定义协议处理该请求。缓存,但我可能是错的。所以可能你的选择是:
在实际处理响应的代码中添加代码,以便识别数据已加密并解密。
例如,您可以在将标题存储到缓存中时向标头插入其他标头,以指示缓存的数据已加密。然后,当你在退路的路上看到魔法标题值时,解密它。