不是每个公司都会以数百美金一年的代价向CA购买SSL证书。在企业应用中,付费的SSL证书经常被自签名证书所替代。当然,对于自签名证书iOS是没有能力验证的。Safari遇到这种无法验证的自签名证书的唯一处理方法,就是将问题扔给用户,让用户决定是否应该相信此类证书。它提供了两个按钮,一个“继续”按钮和一个“取消”按钮。当你点击“取消”按钮,则你将无法访问所请求的资源。 当你点击“继续”按钮,则Safari会认为用户授权它放弃对该服务器的验证,所产生的风险由用户自己承担。 当然,HTTPS传输仍然是加密的。

一、配置HTTPS服务器

我们将使用Tomcat来配置HTTPS服务器。关于Tomcat在mac下的安装,请参考《 安装Tomcat到Mac OSX 》一文。如果你安装了Eclipse,则很可能Eclipse IDE中已经配置过Tomcat。带开Eclipse的“偏好设置”,在Server->RuntimeEnvironments中可以看到已安装好的Tomcat服务器:

点击打开链接

点击“Edit…”按钮,你可以找到Tomcat安装路径:

点击打开链接

打开“终端”,进入Tomcat安装目录:

cd /Library/Tomcat/apache-tomcat-7.0.14

运行以下命令:

keytool -genkey -v -alias tomcat-keyalg RSA -storetype JKS -keystore tomcat.keystore -dname"CN=www.handtimes.com,OU=ipcc,O=云电同方,L=昆明,ST=云南,C=中国" -storepass 123456 -keypass 123456

这将在Tomcat安装路径下生成服务器证书及密钥库(库名:tomcat,文件名:tomcat.keystore),证书是自签名的,证书机构采用域名。密钥库密码和私钥密码都是123456。默认过期时间为3个月(90天)。

注意:-storetype JKS指定了密钥库的类型为java key store。这很重要,如果你指定为其他类型如PKCS12,则Tomcat会报"Invalidkeystore format"错误。

打开tomcat目录下的server.xml,你可以直接从Finder中打开它,或者在Eclipse的Servers项目中编辑这个文件 。

查找 <Connector port="8443",将此段代码的注释取消:

<Connectorport="8443" protocol="HTTP/1.1" SSLEnabled="true"

maxThreads="150" scheme="https"secure="true"

clientAuth="false" sslProtocol="TLS" />

在其中加入两个属性:

keystoreFile="/Library/Tomcat/apache-tomcat-7.0.14/tomcat.keystore"

keystorePass="123456"

注意,本文中的keytool工具使用的是sun/oracle JDK的版本。如果你的机器上安装的是GNU jvm,则keytool应该是GNU的版本,则上述server.xml代码中还应该加入以下属性:

keystoreType="gkr"algorithm="JessieX509"

在Eclipse中编辑完server.xml,然后使用“Run As->Run Configurations…->Run”使修改生效,Eclipse会自动重启Tomcat,但控制台输出如下内容时,表明https服务已经启动:

信息: StartingProtocolHandler ["http-bio-8443"]

2012-7-9 11:29:01org.apache.coyote.AbstractProtocolHandler start

此时,使用HTTPS端口8443随便访问一个页面,例如: https://localhost:8443/AnyMail/table_css_test.html

此时safari会弹出一个窗口提示用户,接收服务器的证书:

点击打开链接

只有点击“继续”,用户才可以访问该页面。

如果你使用FireFox,则需要将此页面添加到例外。

二、iOS 访问HTTPS

新建Single View Application。在ViewController.xib上拖入一个按钮,一个UILabel和一个UIWebView,并连接到源代码。

点击打开链接

打开ViewController.h,声明如下成员:

NSURLRequest* _request;

NSURLConnection *  connection;

NSString* filePath;

NSOutputStream *  fileStream;

NSURL* url,*baseUrl;

NSStringEncoding enc;

NSURLAuthenticationChallenge *_challenge;

_request和connection对象不用多说,我们准备使用URLRequest和URLConnection来请求HTTPS。

程序中将向HTTPS服务器请求一个html文件,这个文件会以临时文件的形式保存到filePath的路径。fileStream则是文件输出流。

url和baseUrl分别指定这个html页面的url地址和base url地址。

enc是服务器页面编码,本例中将使用GBK编码。

由于HTTPS服务器采用了自签名的证书,iOS无法验证此类证书, 所以客户端会向用户索要一个凭据(即Credential,用户对此证书采取什么样的信任策略)。在Safari中,是通过前图所示的那个“服务器证书”窗口来进行的。而在我们的程序中,这个窗口会用一个AlertView替代,服务器询问时的相关内容会封装在一个NSURLAuthenticationChallenge对象中(包括服务器证书),我们以_challenge成员retain它。

使用NSURLConnection请求一个网页资源很简单,这个过程在按钮的触摸事件中触发:

- (IBAction)goAction:(id)sender {

_challenge=nil;

filePath = [[[AppDelegatesharedAppDelegate] pathForTemporaryFileWithPrefix:@"Get"]retain];

NSLog(@"filePath=%@",filePath);

fileStream = [[NSOutputStreamalloc]initToFileAtPath:filePathappend:NO];

assert(fileStream != nil);

[fileStreamopen];

_request = [NSURLRequestrequestWithURL:url];

assert(_request != nil);

connection = [NSURLConnectionconnectionWithRequest:_requestdelegate:self];

}

在方法中我先打开了NSOutputStream 对象,以便将网页写入到临时文件中。这里本来想实现一种缓存机制,不过由于时间原因,我没有再深究下去,导致多次请求后在tmp文件夹中留下了一堆的临时文件。临时文件的文件名是以Get+UUID命名的,我把命名方法写在了AppDelegate里,希望你能找到并解决这个我遗留下来的问题:

点击打开链接

重要的是[NSURLConnectionconnectionWithRequest:delegate:]方法的调用,我们获取了一个NSURLConnection对象并将它的delegate设置为self。

self在实现NSULConnectionDelegate方法时,特别实现了connection:canAuthenticateAgainstProtectionSpace:方法,以及connection:didReceiveAuthenticationChallenge:方法:

- (BOOL)connection:(NSURLConnection *)conncanAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace

{

NSLog(@"authenticatemethod:%@",protectionSpace.authenticationMethod);

return [protectionSpace.authenticationMethodisEqualToString:

NSURLAuthenticationMethodServerTrust];

}

- (void)connection:(NSURLConnection *)conndidReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

{

_challenge=[challenge retain];

UIAlertView* alertView = [[[UIAlertViewalloc] initWithTitle:@"服务器证书"

message:@"这个网站有一个服务器证书,点击“接受”,继续访问该网站,如果你不确定,请点击“取消”。"

delegate:self

cancelButtonTitle:@"接受"

otherButtonTitles:@"取消", nil] autorelease];

[alertView show];

}

canAuthenticateAgainstProtectionSpace:方法在连接到一些有安全限制的网站时调用,例如:服务器信任、客户端证书、HTTP表单验证等。但URLConnection不知道也没有强制程序员必需处理哪些安全问题,因此它把一个NSURLProtectionSpace对象作为参数传递,如果程序员想响应某一类安全问题,那么在这个方法最后就返回YES。你要明白程序员可以处理哪些安全问题,你可以查看NSURLProtectionSpace的authenticationMethod属性。这是一个NSString属性,可能取值包括以下常量:

NSString *NSURLAuthenticationMethodDefault;

NSString*NSURLAuthenticationMethodHTTPBasic;

NSString*NSURLAuthenticationMethodHTTPDigest;

NSString*NSURLAuthenticationMethodHTMLForm;

NSString*NSURLAuthenticationMethodNegotiate;

NSString*NSURLAuthenticationMethodNTLM;

NSString*NSURLAuthenticationMethodClientCertificate;

NSString*NSURLAuthenticationMethodServerTrust;

当然在这里,我们只处理“服务器信任”的安全问题。

didReceiveAuthenticationChallenge方法则紧接第一个方法之后调用。如果第一个方法中返回true,那么URLConnection接下来就调用delegate的第二个方法(NO则跳过第二个方法)。

在这里,我们弹出了一个UIAlertView,提示用户进行处理。

接下来实现UIAlertView的delegate方法:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

// Accept=0,Cancel=1;

if(buttonIndex==0){

NSURLCredential *   credential;

NSURLProtectionSpace *  protectionSpace;

SecTrustRef            trust;

NSString *              host;

SecCertificateRef      serverCert;

assert(_challenge !=nil);

protectionSpace = [_challengeprotectionSpace];

assert(protectionSpace != nil);

trust = [protectionSpaceserverTrust];

assert(trust != NULL);

credential = [NSURLCredentialcredentialForTrust:trust];

assert(credential != nil);

host = [[_challengeprotectionSpace] host];

if (SecTrustGetCertificateCount(trust) > 0) {

serverCert = SecTrustGetCertificateAtIndex(trust, 0);

} else {

serverCert = NULL;

}

[[_challengesender] useCredential:credential forAuthenticationChallenge:_challenge];

}

}

这个方法中,如果用户选择“接受”,则我们从NSURLAuthenticationChallenge对象中获取服务器证书,并将该证书应用于URLConnection,接下来会继续调用URLConnection的其他delegate方法。如果用户选择“取消”,则会导致服务器返回一个错误,这会调用connection:didFailedWithError:方法。

其它方法请自行参考源代码:资源下载

iOS: HTTPS 与自签名证书相关推荐

  1. 生成服务器证书 启用HTTPS 生成自签名证书

    HTTPS的传输过程需要使用公私钥对收发数据进行加密,为了防止中间人攻击,需要在服务器端配置证书,通常,证书由可信的CA(Certificate Authority,数字证书认证中心)机构颁发,但是需 ...

  2. linux 安装ios jenkins 打包机器签名证书问题

    使用jenkins 搭建 ios 打包和质量构建机器,jenkins需要安装xcode工具,同时slave机器必须是ios机器. 因为jenkins ios插件和slave 中的ios 机器上的xco ...

  3. https遇到自签名证书/信任证书

    对于CA机构颁发的证书Okhttp默认支持 可以直接访问 但是对于自定义的证书就不可以了(如:https ://kyfw.12306.cn/otn/), 需要加入Trust 下面分两部分来写,一是信任 ...

  4. 怎么让 chrome 信任自签名证书(亲测有效)

    https本地自签名证书添加到信任证书访问 1.背景 本文适用于基于https(http+ssl)的网站通信.本地调试等,上线是请寻找免费 ssl证书申请. 本地调试过程中,一些特殊的场景需要我使用h ...

  5. iOS使用自签名证书实现HTTPS请求

    原文链接:http://www.jianshu.com/p/e6a26ecd84aa 由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS ...

  6. iOS 用自签名证书实现 HTTPS 请求的原理实例讲解

    在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...

  7. iOS开发HTTPS实现之信任SSL证书和自签名证书

    首先来分析一下什么是HTTPS以及了解HTTPS对于iOS开发者的意义 HTTPS 以及SSL/TSL 什么是SSL? SSL(Secure Sockets Layer, 安全套接字层),因为原先互联 ...

  8. iOS 用自签名证书实现 HTTPS 请求的原理

    在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...

  9. iOS https 自制证书 单向 双向 验证,以及服务器(Nginx)配置

    一.http和https的区别与原理 介绍原理的博文太多了,这里列出一篇详细的: IOS 使用自签名证书开发HTTPS文件传输 二.证书的类型和自制证书生成 1.什么是数字证书(Certificate ...

最新文章

  1. HDU-2084 数塔 经典dp,水
  2. C++网络包截取开发
  3. 数据结构与算法书籍推荐
  4. 贷款审批时,会重点看征信报告哪些内容?
  5. 联想w540笔记本参数_2020年12月笔记本电脑推荐!联想、惠普、华为笔记本电脑推荐!18款高性价比笔记本电脑推荐!!!...
  6. hdb3编码规则波形_光电编码器都归入8543吗?
  7. js时间戳(代码合集)获取(年月日,秒戳,毫秒戳,) - 综合篇
  8. pytorch torch.ones
  9. Spring Boot 启动类真的是XXApplication?
  10. 目录 1. Java中使用Ognl表达式引擎 1 1.1.1. 一、Ognl简介 1 1.1.2. 二、Ognl应用场景 1 1.2. 基本介绍 vs 模板语言 2 1.Java中使用Ognl表达
  11. eclipse汉化完成常见问题的解决方案
  12. Flutter安装依赖包
  13. 颈椎前路caspar撑开器_Caspar撑开器和颈椎带锁钢板治疗下颈椎骨折脱位
  14. SpringBoot_快速实战搭建项目
  15. Apple Pay初探
  16. 【Linux】 基础入门 全解
  17. openstack学习笔记六 多节点部署之keystone
  18. Nacos配置热更新两种方式。
  19. 关于android接入微信分享(以及app签名 the apk for your currently selected variant(app-release)
  20. 互联网晚报 | 10月10日 星期日 | 湖南卫视回应《快本》停播传言;淘特上线微信扫码付;SpaceX成全球第二大创业公司...

热门文章

  1. 在cadence中使用VerilogA
  2. php算html语言吗,为何说PHP 是一种 HTML 内嵌式的语言
  3. rx 6700xt性能相当于什么水平 rx 6700XT参数
  4. 【服务治理】服务注册与发现
  5. 十一丶面向对象的程序设计
  6. 牛客小白月赛19A:「水」滔天巨浪
  7. 从 Hadoop 到云原生:Kyligence 在云原生巨浪中的思考(1)
  8. AI开源的硬核战场:领军者百度如何亮剑?
  9. 李沐精读论文:ViT 《An Image Is Worth 16x16 Words: Transformers For Image Recognition At Scale》
  10. 用express和vue构建全栈项目myweb