昨天给php同事帮忙配置https,现在把过程记录如下:
服务器:CentOS
nginx版本:1.10.0
php版本:5.6.22
同事之前已经把http配置好的。
一、nginx https 配置
开始我真是不懂这方面的,于是百度---怎么给php配置https,得到的答案是https与php无关,应该配置的是nginx,于是我找到了这个教程:http://blog.csdn.net/tiantiandjava/article/details/39077107 看样子一点也不难啊。
生成证书和密钥后,美滋滋打开nginx.conf填入配置(在生成证书的时候需要填写Comom Name 我随便写了一个jason.com 这个是你服务器的根域名 比如 xxx.com 反正是自签名证书 到时候客户端做跳过域名验证就可以了)
然后
curl -k https://localhost:443 (因为CentOS没有浏览器呀 -k参数是忽略证书) 结果Conect Refuse
于是我从网上copy了一个模版修改了一下
server {
listen 443;
server_name www.XXX.com;
ssl on;
ssl_certificate /usr/local/nginx/conf/ssl/xxx.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/xxx_nopwd.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
但是通过浏览器访问这台服务器https://192.168.1.xxx:443/index.html 还是被拒绝。
弄了很久才发现是iptables防火墙的问题
service iptables status 查看防火墙已开启的端口,发现没有443
加上后就可以了,具体可以参考这个链接:http://blog.csdn.net/youcharming/article/details/41986709
二、静态服务器https配置好了,现在是和php连接起来。
你需要在上面的配置里面加上这几行
location ~ \.php$ {
root php文件的根目录;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
什么是fastcgi呢?这要从nginx与php结合的原理来说,nginx只是作静态服务器,而关于php脚本解析要交给专门的进程,它就是fastcgi,
fastcgi_pass 127.0.0.1:9000 就是nginx通过tcp的形式与fastcgi通信。(其实是和fastcgi的管理进程php-fpm进行通信)
具体可以参考这个链接:http://www.nginx.cn/231.html
但是出错了 服务器没响应 查看9000端口根本没打开 再查看php-fpm进程明明已经在运行啊 于是猜想应该是端口不匹配。
然后查看php-fpm的端口信息: netstat -anp | grep php-fpm
unix 2 [ ACC ] STREAM LISTENING 105785 23163/php-fpm /tmp/php-cgi.sock
开头的unix说明是sock通信而不是nginx.conf里配置的127.0.0.1:9000 (tcp通信) 我给个nginx的tcp通信作为参照
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1986/nginx
于是返回nginx.conf修改配置如下:
location ~ \.php$ {
root php文件的根目录;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
然后就完成了代理php的配置。
三、下面来讲讲什么是https
我一直是以两种加密方式来理解https通信过程的:
1.客户端发起https请求
2.服务器返回证书(xxx.crt文件)
3.客户端验证服务器证书,如果没问题将客户端密钥用这个证书加密
4.服务器用自己的私钥解密(xxx_nopwd.key) 从而拿到客户端密钥
(1-4步做了客户端对服务器的单向认证 1-4使用了非对称加密进行认证通信)
5.服务器使用客户端密钥与客户端通信
(之后的通信都是对称加密通信了)
四、给iOS App配置https
ios sdk9.0以后都是默认使用tsl1.2协议进行https通信 但是为了能使用http 我就把App Transport Security Settings设置为允许http传输
现在我想https http 能同时使用 方法很简单:
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"证书名称" ofType:@"cer"];//证书的路径
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// 允许自签名证书
securityPolicy.allowInvalidCertificates = YES;
// 不验证域名
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = [NSSet setWithObjects:certData, nil];
上面那个.cer证书就是你服务器传过来的那个.crt经过转换为了.cer 具体获取方法可以在这个链接里面找 http://www.jianshu.com/p/fa65eb0460dc
其实如果只是做客户端对服务器的单向认证(比如我上面搭建的nginx),不认证客户端的话可以不用在ios程序里面放证书。
但是会被代理服务器抓包。具体可以参考这篇文章:http://www.jianshu.com/p/97745be81d64
如果要做双向认证nginx配置要加上一些东西,比如ssl_client_certificate xx/xxx/xx.crt
可以参考这篇文章:http://www.tuicool.com/articles/FrUZJze
这样从服务器到客户端的配置就基本完成了
文中有很多个人理解的地方 所以难免出现错漏 今天特意总结出来 仅供参考