Joh*_*rck 59 iphone ssl objective-c ios ios7
我正在开发一款iPhone应用程序.在开发期间,我需要连接到使用自签名SSL证书的服务器.我很确定- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
我有机会编写一些异常代码来实现这一点.但是,我找不到任何资源告诉我如何做到这一点.我可以在日志中看到以下错误:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
Run Code Online (Sandbox Code Playgroud)
除此之外,当我NSLog(@"error = %@", error);
从上面的委托方法中得到:
错误域= NSURLErrorDomain代码= -1202"此服务器的证书无效.您可能正在连接到假装为"api.mydevelopmenturl.com"的服务器,这可能会使您的机密信息面临风险." UserInfo = 0x10cbdbcf0 {NSUnderlyingError = 0x112ec9730"此服务器的证书无效.您可能正在连接到假装为"api.mydevelopmenturl.com"的服务器,这可能会使您的机密信息面临风险.",NSErrorFailingURLStringKey = https: //api.mydevelopmenturl.com/posts,NSErrorFailingURLKey = https://api.mydevelopmenturl.com/posts,NSLocalizedRecoverySuggestion =您是否还要连接到服务器?,NSURLErrorFailingURLPeerTrustErrorKey =,NSLocalizedDescription =此服务器的证书无效.您可能正在连接到假装为"api.mydevelopmenturl.com"的服务器,这可能会使您的机密信息面临风险.}
有关如何解决此问题的任何想法?请在我阅读概念文档时发布代码,但我不理解它们.这是一个超越我的例子:https://developer.apple.com/library/content/technotes/tn2232/_index.html
小智 113
这对我有用:
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:Nil];
...
...
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler{
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
if([challenge.protectionSpace.host isEqualToString:@"mydomain.com"]){
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
}
}
Run Code Online (Sandbox Code Playgroud)
mem*_*ons 26
Apple有一个技术说明2232,它提供了非常丰富的信息,并详细解释了HTTPS服务器信任评估.
在这种情况下,NSURLErrorDomain
域中的错误-1202 NSURLErrorServerCertificateUntrusted
,这意味着服务器信任评估失败.您可能还会收到各种其他错误; 附录A:通用服务器信任评估错误列出了最常见的错误.
来自技术说明:
在大多数情况下,解决服务器信任评估失败的最佳方法是修复服务器.这有两个好处:它提供了最佳的安全性,并减少了您必须编写的代码量.本技术说明的其余部分描述了如何诊断服务器信任评估失败,以及如果无法修复服务器,如何自定义服务器信任评估以允许连接继续进行而不会完全破坏用户的安全性.
与此问题密切相关的特定位是NSURLSession服务器信任评估部分:
NSURLSession
允许您通过实现-URLSession:didReceiveChallenge:completionHandler:
委托方法来自定义HTTPS服务器信任评估.要自定义HTTPS服务器信任评估,请查找其保护空间具有身份验证方法的质询NSURLAuthenticationMethodServerTrust
.对于这些挑战,请按照以下说明解决它们.对于其他挑战,您不关心的挑战,使用NSURLSessionAuthChallengePerformDefaultHandling
处置和NULL凭证调用完成处理程序块 .处理NSURLAuthenticationMethodServerTrust身份验证质询时,可以通过调用-serverTrust方法从质询的保护空间中获取信任对象.使用信任对象进行自定义HTTPS服务器信任评估后,必须以下列两种方式之一解决该问题:
如果要拒绝连接,请使用
NSURLSessionAuthChallengeCancelAuthenticationChallenge
处置和NULL凭证调用完成处理程序块.如果要允许连接,请从您的信任对象(使用
+[NSURLCredential credentialForTrust:]
)创建凭证,并使用该凭据和NSURLSessionAuthChallengeUseCredential
处置调用完成处理程序块 .
所有这些的结果是,如果您实现以下委托方法,您可以覆盖特定服务器的服务器信任:
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
if([challenge.protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if([challenge.protectionSpace.host
isEqualToString:@"domaintoverride.com"])
{
NSURLCredential *credential =
[NSURLCredential credentialForTrust:
challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
else
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,你必须处理两个匹配要覆盖一个主机的情况下,与所有其他情况.如果您不处理"所有其他情况"部分,则行为结果未定义.
Joh*_*rck 12
在线查找受信任的SSL证书颁发机构,为新证书提供90天免费试用.在您的服务器上安装证书.您现在有90天的时间来开发您的应用程序,以便您可以决定是否值得花钱来"续订"证书.这对我来说是最好的答案,因为我决定使用自签名证书是出于财务上的动机,90天给了我足够的时间来开发我的应用程序,以便我可以决定是否值得花钱在SSL证书上.这种方法避免了必须处理运行调整的代码库以接受自签名证书的安全隐患.甜!对于自举!
Sha*_*rog 11
做自己一个巨大的帮助而不是.
首先阅读论文世界上最危险的代码:验证非浏览器软件中的SSL证书,尤其是第10节"打破或禁用证书验证".它专门引用了一个与Cocoa相关的博客,专门描述了如何做你所要求的.
但不要.禁用SSL证书检查就像在您的应用中引入滴答作响的定时炸弹.有一天,有一天,它会不小心被启用,并且构建将进入狂野状态.在那一天,您的用户将面临严重的风险.
相反,您应该使用一个证书,该证书使用您可以在该特定设备上安装和信任的中间证书进行签名,这将允许SSL验证成功,而不会危及除您自己之外的任何其他设备(并且仅暂时).
小智 6
与friherd的解决方案相同,但在swift中:
func URLSession(session: NSURLSession, task: NSURLSessionTask, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust{
let credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential,credential);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您只想允许任何类型的自签名证书,则可以使用以下方法来实现URLSessionDelegate。Apple提供了有关如何将URLSessionDelegate用于各种身份验证方法的附加信息:https : //developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/AuthenticationChallenges.html
首先,实现委托方法并分配一个相应的委托:
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let task = urlSession.dataTask(with: urlRequest).resume()
Run Code Online (Sandbox Code Playgroud)
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.previousFailureCount == 0 else {
challenge.sender?.cancel(challenge)
// Inform the user that the user name and password are incorrect
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
// Within your authentication handler delegate method, you should check to see if the challenge protection space has an authentication type of NSURLAuthenticationMethodServerTrust
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
// and if so, obtain the serverTrust information from that protection space.
&& challenge.protectionSpace.serverTrust != nil
&& challenge.protectionSpace.host == "yourdomain.com" {
let proposedCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(URLSession.AuthChallengeDisposition.useCredential, proposedCredential)
}
}
Run Code Online (Sandbox Code Playgroud)
不过,您可以根据自己提供的域调整对任何自签名证书的接受程度,以匹配非常特定的域。确保已将此证书添加到构建目标捆绑包中。我在这里命名为“ cert.cer”
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.previousFailureCount == 0 else {
challenge.sender?.cancel(challenge)
// Inform the user that the user name and password are incorrect
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
&& challenge.protectionSpace.serverTrust != nil
&& challenge.protectionSpace.host == "yourdomain.com" {
if let trust = challenge.protectionSpace.serverTrust,
let pem = Bundle.main.url(forResource:"cert", withExtension: "cer"),
let data = NSData(contentsOf: pem),
let cert = SecCertificateCreateWithData(nil, data) {
let certs = [cert]
SecTrustSetAnchorCertificates(trust, certs as CFArray)
var result=SecTrustResultType.invalid
if SecTrustEvaluate(trust,&result)==errSecSuccess {
if result==SecTrustResultType.proceed || result==SecTrustResultType.unspecified {
let proposedCredential = URLCredential(trust: trust)
completionHandler(.useCredential,proposedCredential)
return
}
}
}
}
completionHandler(.performDefaultHandling, nil)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
69199 次 |
最近记录: |