iOS网络——身份认证
发布日期:2022-03-18 08:27:43 浏览次数:38 分类:技术文章

本文共 10103 字,大约阅读时间需要 33 分钟。

iOS网络身份认证

文档

中重要的类如下:

这里写图片描述

在中的配置身份认证(Configuring Authentication),摘录如下:

对于NSURLSession,代理对象要实现URLSession:task:didReceiveChallenge:completionHandler:方法。

对于NSURLConnection类:

  • OS X v10.7和iOS5及以上的,代理对象要显示connection:willSendRequestForAuthenticationChallenge: 方法。
  • 在早期的版本中,代理对象要实现connection:canAuthenticateAgainstProtectionSpace:connection:didReceiveAuthenticationChallenge:方法。

中的Authentication Challenges and TLS Chain Validation有如何响应认证请求?(Deciding How to Respond to an Authentication Challenge)

  • NSURLSession: 所有的认证请求都被传递给代理对象,不论它是什么认证类型
  • NSURLConnection或者NSURLDownload: 代理对象收到connection:canAuthenticateAgainstProtectionSpace:(或者download:canAuthenticateAgainstProtectionSpace:)消息,允许代理,在尝试来验证它之前,来分析服务器的属性,包括它的协议和认证方法。如果代理不打算来验证服务器的protection space,返回NO。然后系统会尝试从用户的keychain来验证信息。
  • 如果NSURLConnection或者NSURLDownload 的代理没有实现connection:canAuthenticateAgainstProtectionSpace:(或者download:canAuthenticateAgainstProtectionSpace:)方法,protection space使用客户端证书认证(client certificate authentication)或者服务器信任认证server trust authentication),系统的行为就像你返回了NO。系统的行为就像对其它的所有的认证类型,你返回的是YES。

接下来,如果代理同意处理认证,并且没有可用的有效证书,无论是请求URL的一部分或者是NSURLCredentialStorage中的共享。代理会收到下面其中之一的消息:

URLSession:didReceiveChallenge:completionHandler:URLSession:task:didReceiveChallenge:completionHandler:connection:didReceiveAuthenticationChallenge:download:didReceiveAuthenticationChallenge:

为了继续连接,代理有如下的三个选择:

  • 提供认证证书
  • 没有证书,尝试继续(Attempt to continue without credentials)
  • 取消认证请求

响应认证请求

响应connection:didReceiveAuthenticationChallenge: 代理方法,有如下3种方式

提供证书(Providing Credentials)

为了认证,要创建一个NSURLCredential对象。在提供的authentication challenge的protection space上调用authenticationMethod 方法,可以获取服务器的认证方法。NSURLCredential支持的认证方法有:

  • HTTP basic authentication (NSURLAuthenticationMethodHTTPBasic) 需要一个用户名和密码。使用
    credentialWithUser:password:persistence:方法创建NSURLCredential对象。
  • HTTP digest authentication (NSURLAuthenticationMethodHTTPDigest),与basic authentication类似,也需要一个用户名和密码。使用
    credentialWithUser:password:persistence:方法创建NSURLCredential对象。
  • Client certificate authentication (NSURLAuthenticationMethodClientCertificate) 需要system identity和需要与server进行身份验证的所有证书。使用credentialWithIdentity:certificates:persistence:创建NSURLCredential对象。
  • Server trust authentication (NSURLAuthenticationMethodServerTrust) 需要authentication challenge的protection space提供一个trust。使用credentialForTrust:来创建NSURLCredential对象。

创建NSURLCredential对象之后:

  • 对于NSURLSession,在completion handler中,把NSURLCredential对象传递给authentication challenge的sender。
  • 对于NSURLConnectionNSURLDownload,使用useCredential:forAuthenticationChallenge: 方法,把NSURLCredential对象传递给authentication challenge的sender。

不提供证书(Continuing Without Credentials)

如果代理选择不提供证书,可选择如下方式来继续:

  • 对于NSURLSession,传递如下之一的值给completion handler回调:
    • NSURLSessionAuthChallengePerformDefaultHandling 处理请求,就好像代理没有提供一个代理方法来处理认证请求
    • NSURLSessionAuthChallengeRejectProtectionSpace 拒接认证请求。基于服务器响应的认证类型,URL加载类可能会多次调用代理方法。
  • 对于 NSURLConnectionNSURLDownload,在[challenge sender] 上调用continueWithoutCredentialsForAuthenticationChallenge:方法。不提供证书的话,可能会导致连接失败,调用connectionDidFailWithError:方法 ,或者会返回一个不需要验证身份的替代的URL。

取消连接(Canceling the Connection)

代理也可以选择取消认证请求(authentication challenge)

  • 对于NSURLSession,传递NSURLSessionAuthChallengeCancelAuthenticationChallenge 到提供的completion handler中。
  • 对于 NSURLConnectionNSURLDownload,在[challenge sender]上调用cancelAuthenticationChallenge: 。代理会收到connection:didCancelAuthenticationChallenge:消息。

身份认证例子

下面的例子使用预先设置的用户名和密码来创建NSURLCredential。如果身份认证先前失败过,就取消认证请求并通知用户。

-(void)connection:(NSURLConnection *)connection        didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{    if ([challenge previousFailureCount] == 0) {        NSURLCredential *newCredential;        newCredential = [NSURLCredential credentialWithUser:[self preferencesName]                                                 password:[self preferencesPassword]                                              persistence:NSURLCredentialPersistenceNone];        [[challenge sender] useCredential:newCredential               forAuthenticationChallenge:challenge];    } else {        [[challenge sender] cancelAuthenticationChallenge:challenge];        // inform the user that the user name and password        // in the preferences are incorrect        [self showPreferencesCredentialsAreIncorrectPanel:self];    }}

如果代理没有实现connection:didReceiveAuthenticationChallenge:方法,并且请求需要认证,URL credential storage中需存在有效的证书或者必须在请求的URL中提供。如果没有证书或者验证失败,代理会调用continueWithoutCredentialForAuthenticationChallenge: 方法。

执行自定义TLS链验证(Performing Custom TLS Chain Validation)

除了提供证书到服务器,app还可以检查在TLS握手过程中服务器提供的证书,然后告知URL加载系统,是否应该接受或者拒接这些证书。

如果你需要以非标准方式来执行TLS链验证(例如接受一个自签名证书来测试),app应该这样做:

  • 对于NSURLSession,实现URLSession:didReceiveChallenge:completionHandler: 或者URLSession:task:didReceiveChallenge:completionHandler:代理方法。如果你两个都实现,session-level方法负责处理身份认证。
  • 对于NSURLConnectionNSURLDownload,实现connection:canAuthenticateAgainstProtectionSpace:或者download:canAuthenticateAgainstProtectionSpace: 方法,如果 protection space有一个认证类型是NSURLAuthenticationMethodServerTrust,返回YES。
    然后,实现connection:didReceiveAuthenticationChallenge: 或者download:didReceiveAuthenticationChallenge: 来处理身份认证。

在身份认证处理方法中,要检查challenge的protection space是否有NSURLAuthenticationMethodServerTrust类型,如果有,就从protection space中获取serverTrust信息。

更多详细信息,请参考

类介绍

相关内容请参加

NSURLProtectionSpace

protection space (also realm) — An HTTP or HTTPS server, or an area on such a server, that requires authentication. Within Foundation this is represented by the NSURLProtectionSpace class. See also authentication challenge.

NSURLProtectionSpace表示需要认证的服务器或者域。

《iOS网络高级编程:iPhone和iPad的企业应用开发》书中介绍如下:
“最佳实践是使用NSURLProtectionSpace 验证手机银行应用的用户与安全的银行服务器进行通信,特别是在发出的请求会操纵后端数据时更是如此”
创建方式如下:

NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:@"67.205.6.121"                                                                        port:443                                                                    protocol:NSURLProtectionSpaceHTTPS                                                                       realm:@"mobilebanking"                                                        authenticationMethod:NSURLAuthenticationMethodClientCertificate];

所有支持的认证方法有:

  • NSURLAuthenticationMethodDefault
  • NSURLAuthenticationMethodHTTPBasic
  • NSURLAuthenticationMethodHTTPDigest
  • NSURLAuthenticationMethodHTMLForm
  • NSURLAuthenticationMethodNTLM
  • NSURLAuthenticationMethodNegotiate
  • NSURLAuthenticationMethodClientCertificate
  • NSURLAuthenticationMethodServerTrust

使用服务器的属性创建了保护空间后,就可以用于验证连接。在代码向需要认证的服务器请求资源时,服务器会使用HTTP状态码401进行响应,即访问拒绝。NSURLConnection会接收到响应并立刻使用认证challenge的一份副本来发送一条willSendRequestForAuthenticationChallenge:委托消息。过程如下所示:

这里写图片描述

NSURLAuthenticationChallenge

NSURLAuthenticationChallenge encapsulates a challenge from a server requiring authentication from the client.

authentication challenge — An HTTP or HTTPS response indicating that the server requires authentication information from the client(服务器从客户端请求的验证信息). Foundation represents this with the NSURLAuthenticationChallenge class, and it also uses this infrastructure to support custom HTTPS server trust evaluation. An authentication challenge originates from a protection space.

NSURLCredential

NSURLCredential代表的是一个身份验证证书。URL Loading系统支持3种类型的证书:password-based user credentials, certificate-based user credentials, and certificate-based server credentials。

NSURLCredential适合大多数的认证请求,因为它可以表示由用户名/密码组合、客户端证书及服务器信任创建的认证信息。
认证信息有三种持久化选项:

  • NSURLCredentialPersistenceNone :要求 URL 载入系统 “在用完相应的认证信息后立刻丢弃”。
  • NSURLCredentialPersistenceForSession :要求 URL 载入系统 “在应用终止时,丢弃相应的 credential ”。
  • NSURLCredentialPersistencePermanent :要求 URL 载入系统 “将相应的认证信息存入钥匙串(keychain),以便其他应用也能使用。

HTTP认证

认证指的是确认访问系统的用户身份的过程。对于手机银行应用的服务层来说,最重要的事情就是要能分辨出真实用户与虚假用户之间的差别。

手机银行应用有两种认证模式:

  • 标准验证:提示用户输入用户名和密码
  • 快速验证:让用户注册设备,然后使用PIN进行验证,每次验证无需用户名和密码。如果用户选择在给定的认证请求中注册设备,那么服务器响应就需要包含一个额外的属性,即用户的证书。应用会存储这个证书,并在随后启动时检查,从而确定应该显示哪个认证视图。

手机银行应用的标准认证模式使用HTTP Basic认证,而快速认证则使用从Web Service下载的客户端证书。

HTTP Basic, HTTP Digest, 与 NTLM认证

Basic、Digest与NTLM认证都是基于用户名/密码的认证。他们认证的响应逻辑是相同的。

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {    // validate that the authentication challenge came from a whitelisted protection space    if (![[[Model sharedModel] validProtectionSpaces] containsObject:challenge.protectionSpace]) {        // dispatch alert view message to the main thread        dispatch_async(dispatch_get_main_queue(), ^{            [[[UIAlertView alloc] initWithTitle:@"Unsecure Connection"                                        message:@"We're unable to establish a secure connection. Please check your network connection and try again."                                       delegate:nil                              cancelButtonTitle:@"OK"                              otherButtonTitles:nil] show];        });        // cancel authentication        [challenge.sender cancelAuthenticationChallenge:challenge];    }    // respond to basic authentication requests    // others that follow this pattern include DIGEST and NTLM authentication    if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic) {        // proceed with authentication        if (challenge.previousFailureCount == 0) {            NSURLCredential *creds = [[NSURLCredential alloc] initWithUser:_username                                                                  password:_password                                                                persistence:NSURLCredentialPersistenceForSession];            [challenge.sender useCredential:creds forAuthenticationChallenge:challenge];        // authentication has previously failed. depending on authentication configuration, too        // many attempts here could lead to a poor user experience via locked accounts        } else {            // cancel the authentication attempt            [[challenge sender] cancelAuthenticationChallenge:challenge];            // alert observers of the failed attempt            dispatch_async(dispatch_get_main_queue(), ^{                [[NSNotificationCenter defaultCenter] postNotificationName:kNormalLoginFailedNotification object:nil];            });        }    }}

基本认证请参考

参考文档

转载地址:https://windzen.blog.csdn.net/article/details/53610157 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:使用AVFoundation来录音并播放
下一篇:iOS网络——socket

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年03月30日 10时41分20秒