php使用curl库进行ssl双向认证

本文介绍了一个使用PHP通过curl实现SSL双向认证的方法,并提供了详细的代码示例。包括设置超时时间、返回数据要求、证书验证等选项。

官方文档:


http://www.php.net/manual/zh/function.curl-setopt.php#10692


官方举例:


<?php

curl_setopt($ch, CURLOPT_VERBOSE, '1');

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '1');

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, '1');

curl_setopt($ch, CURLOPT_CAINFO, getcwd().'/cert/ca.crt');

curl_setopt($ch, CURLOPT_SSLCERT, getcwd().'/cert/mycert.pem');

curl_setopt($ch, CURLOPT_SSLCERTPASSWD, 'password');

?>


由于业务原因,后台登陆需要使用SSL双向认证,即web服务器有证书,浏览器客户端也需要安装证书

然后这样的话,php接口文件就需要走443端口来访问了

直接附上代码:


/**
 * @name ssl Curl Post数据
 * @param string $url 接收数据的api
 * @param string $vars 提交的数据
 * @param int $second 要求程序必须在$second秒内完成,负责到$second秒后放到后台执行
 * @return string or boolean 成功且对方有返回值则返回
 */
function curl_post_ssl($url, $vars, $second=30,$aHeader=array())
{
                $ch = curl_init();
                //curl_setopt($ch,CURLOPT_VERBOSE,'1');
                curl_setopt($ch,CURLOPT_TIMEOUT,$second);
                curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch,CURLOPT_URL,$url);
                curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
                curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
                curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
                curl_setopt($ch,CURLOPT_SSLCERT,'/data/cert/php.pem');
                curl_setopt($ch,CURLOPT_SSLCERTPASSWD,'1234');
                curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
                curl_setopt($ch,CURLOPT_SSLKEY,'/data/cert/php_private.pem');
 
                if( count($aHeader) >= 1 ){
                        curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
                }
 
                curl_setopt($ch,CURLOPT_POST, 1);
                curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
                $data = curl_exec($ch);
                curl_close($ch);
                if($data)
                        return $data;
                else   
                        return false;
}


参数解释:

CURLOPT_TIMEOUT:超时时间

CURLOPT_RETURNTRANSFER:是否要求返回数据

CURLOPT_SSL_VERIFYPEER:是否检测服务器的证书是否由正规浏览器认证过的授权CA颁发的

CURLOPT_SSL_VERIFYHOST:是否检测服务器的域名与证书上的是否一致

CURLOPT_SSLCERTTYPE:证书类型,"PEM" (default), "DER", and"ENG".

CURLOPT_SSLCERT:证书存放路径

CURLOPT_SSLCERTPASSWD:证书密码

CURLOPT_SSLKEYTYPE:私钥类型,"PEM" (default), "DER", and"ENG".

CURLOPT_SSLKEY:私钥存放路径


由于php的curl只支持pem格式、der、eng格式,而之前生成的是p12的格式,所以需要转换一下

PKCS#12 到 PEM 的转换

openssl pkcs12 -nocerts -nodes -in cert.p12 -out private.pem

验证

openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem


转载:http://www.cnblogs.com/freespider/p/3622830.html




下面接着转一篇curl如何使用代理访问服务器


$proxy = "80.25.198.25";
$proxyport = "8080";
$ch = curl_init("http://sfbay.craigslist.org/");

curl_setopt($ch, curlOPT_RETURNTRANSFER,1);
curl_setopt($ch,curlOPT_proxy,$proxy);
curl_setopt($ch,curlOPT_proxyPORT,$proxyport);
curl_setopt ($ch, CURLOPT_TIMEOUT, 120);

$result = curl_exec($ch);
echo $result;

curl_close($ch);


<think>问题:cURL 错误: SSL certificate problem: self signed certificate 原因:这个错误是因为cURL在验证SSL证书时发现该证书是自签名的(即不是由受信任的证书颁发机构CA签发的),因此cURL默认会拒绝连接。 解决方案: 1. 如果是测试环境,可以选择忽略证书验证(不推荐生产环境使用)。 2. 将自签名证书添加到受信任的根证书列表中。 3. 或者,在请求中指定该自签名证书为信任证书。 下面分别给出几种解决方案的代码示例:</think>### 解决 "SSL certificate problem: self signed certificate" 错误 这个错误表示 cURL 遇到了自签名证书(不是由受信任的证书颁发机构 CA 签发的)。以下是几种解决方案,根据您的使用场景选择: --- #### 方案 1:临时禁用 SSL 验证(仅限测试环境) ```php <?php $ch = curl_init("https://your-api-url.com"); // 禁用 SSL 验证(仅测试环境使用curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 0 = 不验证主机名 // 其他设置 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); if (curl_errno($ch)) { die("cURL 错误: " . curl_error($ch)); } curl_close($ch); echo $response; ?> ``` > **警告**:此方法会禁用所有 SSL/TLS 安全检查,使连接容易受到中间人攻击。**切勿在生产环境中使用**。 --- #### 方案 2:信任特定自签名证书(推荐) 1. **获取服务器证书**: ```bash openssl s_client -connect your-api-url.com:443 -showcerts </dev/null 2>/dev/null | sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' > server-cert.pem ``` 2. **在 PHP 代码中指定证书**: ```php <?php $ch = curl_init("https://your-api-url.com"); // 指定自签名证书路径 curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/server-cert.pem'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 严格验证主机名 // 其他设置 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); if (curl_errno($ch)) { die("cURL 错误: " . curl_error($ch)); } curl_close($ch); echo $response; ?> ``` --- #### 方案 3:将证书添加到系统信任(永久解决方案) 1. **查找系统 CA 证书路径**: ```php <?php phpinfo(); // 查找 "curl.cainfo" 或 "openssl.cafile" ?> ``` 2. **将自签名证书添加到 CA 包**: ```bash # 将自签名证书附加到 CA 包 cat server-cert.pem >> /etc/ssl/certs/ca-certificates.crt # 或指定到 PHP 配置 # 在 php.ini 中添加: # curl.cainfo = "/path/to/your/ca-bundle.crt" # openssl.cafile = "/path/to/your/ca-bundle.crt" ``` --- #### 方案 4:使用 Guzzle HTTP 客户端(更灵活) ```php <?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; // 创建自定义处理自签名证书的客户端 $client = new Client([ 'verify' => false, // 禁用验证(测试环境) // 或指定证书路径 // 'verify' => __DIR__ . '/server-cert.pem', 'timeout' => 10, 'headers' => [ 'User-Agent' => 'MyApp/1.0', ] ]); try { $response = $client->get('https://your-api-url.com'); echo $response->getBody(); } catch (RequestException $e) { die("请求失败: " . $e->getMessage()); } ?> ``` --- ### 最佳实践建议 1. **开发/测试环境**: - 使用方案 1(临时禁用验证) - 或使用方案 2(信任特定证书) 2. **生产环境**: - 使用方案 3(添加到系统信任) - 或使用受信任的 CA 证书替代自签名证书(如 Let's Encrypt) 3. **证书管理**: - 定期更新自签名证书(通常有效期 1 年) - 使用 `openssl x509 -in server-cert.pem -text -noout` 检查证书详情 4. **安全注意事项**: - 永远不要在生产环境中禁用 SSL 验证 - 自签名证书提供加密但不提供身份验证 - 考虑使用 mTLS(双向 TLS)进行更严格的身份验证 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值