# SSL支持
---
[TOC]
本章將詳細講解如何制作證書以及如何開啟Swoole的SSL的單向、雙向認證。
## 準備工作
選擇任意路徑,執行如下命令創建文件夾結構
```shell
mkdir ca
cd ca
mkdir private
mkdir server
mkdir newcerts
```
在ca目錄下創建`openssl.conf`文件,文件內容如下
```
[ ca ]
default_ca = foo # The default ca section
[ foo ]
dir = /path/to/ca # top dir
database = /path/to/ca/index.txt # index file.
new_certs_dir = /path/to/ca/newcerts # new certs dir
certificate = /path/to/ca/private/ca.crt # The CA cert
serial = /path/to/ca/serial # serial no file
private_key = /path/to/ca/private/ca.key # CA private key
RANDFILE = /path/to/ca/private/.rand # random number file
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = md5 # message digest method to use
unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
policy = policy_any # default policy
[ policy_any ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = match
localityName = optional
commonName = optional
emailAddress = optional
```
其中,`/path/to/ca/`是ca目錄的絕對路徑。
## 創建ca證書
在ca目錄下創建一個shell腳本,命名為`new_ca.sh`。文件內容如下:
```bash
#!/bin/sh
openssl genrsa -out private/ca.key
openssl req -new -key private/ca.key -out private/ca.csr
openssl x509 -req -days 365 -in private/ca.csr -signkey private/ca.key -out private/ca.crt
echo FACE > serial
touch index.txt
openssl ca -gencrl -out private/ca.crl -crldays 7 -config "./openssl.conf"
```
執行`sh new_ca.sh`命令,創建ca證書。生成的證書存放于private目錄中。
> **注意**
在創建ca證書的過程中,需要輸入一些信息。其中,countryName、stateOrProvinceName、organizationName、organizationalUnitName這四個選項的內容必須要填寫,并且需要記住。在生成后續的證書過程中,要保證這四個選項的內容一致。
## 創建服務端證書
在ca目錄下創建一個shell腳本,命名為`new_server.sh`。文件內容如下:
```bash
#!/bin/sh
openssl genrsa -out server/server.key
openssl req -new -key server/server.key -out server/server.csr
openssl ca -in server/server.csr -cert private/ca.crt -keyfile private/ca.key -out server/server.crt -config "./openssl.conf"
```
執行`sh new_ca.sh`命令,創建ca證書。生成的證書存放于server目錄中。
## 創建客戶端證書
在ca目錄下創建一個shell腳本,命名為`new_client.sh`。文件內容如下:
```bash
#!/bin/sh
base="./"
mkdir -p $base/users/
openssl genrsa -des3 -out $base/users/client.key 1024
openssl req -new -key $base/users/client.key -out $base/users/client.csr
openssl ca -in $base/users/client.csr -cert $base/private/ca.crt -keyfile $base/private/ca.key -out $base/users/client.crt -config "./openssl.conf"
openssl pkcs12 -export -clcerts -in $base/users/client.crt -inkey $base/users/client.key -out $base/users/client.p12
```
執行`sh new_ca.sh`命令,創建ca證書。生成的證書存放于users目錄中。
進入users目錄,可以看到有一個`client.p12`文件,這個就是客戶端可用的證書了,但是這個證書是不能在php中使用的,因此需要做一次轉換。命令如下:
```shell
openssl pkcs12 -clcerts -nokeys -out cer.pem -in client.p12
openssl pkcs12 -nocerts -out key.pem -in client.p12
```
以上兩個命令會生成cer.pem和key.pem兩個文件。其中,生成key.pem時會要求設置密碼,這里記為`client_pwd`
> **注意**
如果在創建客戶端證書時,就已經給client.p12設置了密碼,那么在轉換格式的時候,需要輸入密碼進行轉換
## 最終結果
以上步驟執行結束后,會得到不少文件,其中需要用的文件如下表所示:
| 文件名 | 路徑 | 說明 |
| --- | --- | --- |
| ca.crt | ca/private/ | ca證書 |
| server.crt | ca/server/ | 服務器端證書 |
| server.key | ca/server/ | 服務器端秘鑰 |
| cer.pem | ca/client/ | 客戶端證書 |
| key.pem | ca/client/ | 客戶端秘鑰 |
# SSL單向認證
## Swoole開啟SSL
Swoole開啟SSL功能需要如下參數:
```php
$server = new swoole_server("127.0.0.1", "9501" , SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL );
$server = new swoole_http_server("127.0.0.1", "9501" , SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL );
```
并在swoole的配置選項中增加如下兩個選項:
```php
$server->set(array(
'ssl_cert_file' => '/path/to/server.crt',
'ssl_key_file' => '/path/to/server.key',
));
```
這時,swoole服務器就已經開啟了單向SSL認證,可以通過`https://127.0.0.1:9501/`進行訪問。
# SSL雙向認證
## 服務器端設置
雙向認證指服務器也要對發起請求的客戶端進行認證,只有通過認證的客戶端才能進行訪問。
為了開啟SSL雙向認證,swoole需要額外的配置參數如下:
```php
$server->set(array(
'ssl_cert_file' => '/path/to/server.crt',
'ssl_key_file' => '/path/to/server.key',
'ssl_client_cert_file' => '/path/to/ca.crt',
'ssl_verify_depth' => 10,
));
```
## 客戶端設置
這里我們使用CURL進行https請求的發起。
首先,需要配置php.ini,增加如下配置:
```
curl.cainfo=/path/to/ca.crt
```
發起curl請求時,增加如下配置項:
```php
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 只信任CA頒布的證書
curl_setopt($ch, CURLOPT_SSLCERT, "/path/to/cer.pem");
curl_setopt($ch, CURLOPT_SSLKEY, "/path/to/key.pem");
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, '******'); // 創建客戶端證書時標記的client_pwd密碼
```
這時,就可以發起一次https請求,并且被swoole服務器驗證通過了。
- swoole簡介
- swoole功能概述
- 序章
- 開發必讀
- 1 環境搭建
- 1.1 環境搭建
- 1.2 搭建Echo服務器
- 2 初識Swoole
- 2.1 Worker進程
- 2.2 TaskWorker進程
- 2.3 Timer定時器
- 2.4 Process進程
- 2.5 Table內存表
- 2.6 多端口監聽
- 2.7 sendfile文件支持
- 2.8 SSL支持
- 2.9 熱重啟
- 2.10 http_server
- 附錄*server配置
- 附錄*server函數
- 附錄*server屬性
- 附錄*server回調函數
- 附錄*server高級特性
- 心跳檢測
- 3 Swoole協議
- 3.1 EOF協議
- 3.2 固定包頭協議
- 3.3 Http協議
- 3.4 WebSocket協議
- 3.5 MTQQ協議
- 內置http_server
- 內置websocket_server
- Swoole\Redis\Server
- 4 Swoole異步IO
- 4.1 AsyncIO
- 異步文件系統IO
- swoole_async_readfile
- swoole_async_writefile
- swoole_async_read
- swoole_async_write
- 5 swoole異步客戶端
- ws_client
- http_client
- mysql_client
- redis_client
- tcp_client
- http2_client
- 6 swoole協程
- Swoole\Coroutine\Http\Client
- Swoole\Coroutine\MySQL
- Swoole\Coroutine\Redis
- Coroutine\PostgreSQL
- Swoole\Coroutine\Client
- Swoole\Coroutine\Socket
- Swoole\Coroutine\Channel
- Coroutine
- Swoole\Coroutine::create
- Swoole\Coroutine::resume
- Swoole\Coroutine::suspend
- Swoole\Coroutine::sleep
- Coroutine::getaddrinfo
- Coroutine::gethostbyname
- swoole_async_dns_lookup_coro
- Swoole\Coroutine::getuid
- getDefer
- setDefer
- recv
- Coroutine::stats
- Coroutine::fread
- Coroutine::fget
- Coroutine::fwrite
- Coroutine::readFIle
- Coroutine::writeFIle
- Coroutine::exec
- 7 swoole_process
- process::construct
- process::start
- process::name
- process::signal
- process::setaffinity
- process::exit
- process::kill
- process::daemon
- process->exec
- process::wait
- process::alarm
- 8 swoole定時器
- swoole_timer_tick
- swoole_timer_after
- swoole_timer_clear
- 9 swoole_event
- swoole_event_add
- swoole_event_set
- swoole_event_del
- swoole_event_wait
- swoole_event_defer
- swoole_event_write
- swoole_event_exit
- swoole提供的function
- 常見問題
- 客戶端鏈接失敗原因
- 如何設置進程數
- 如何實現異步任務
- 如何選擇swoole三種模式
- php中哪些函數是阻塞的
- 是否可以共用1個redis或mysql連接
- 如何在回調函數中訪問外部的變量
- 為什么不要send完后立即close
- 不同的Server程序實例間如何通信
- MySQL的連接池、異步、斷線重連
- 在php-fpm或apache中使用swoole
- 學習Swoole需要掌握哪些基礎知識
- 在phpinfo中有在php-m中沒有
- 同步阻塞與異步非阻塞選擇
- CURL發送POST請求服務器端超時
- 附錄
- 預定義常量
- 內核參數調優
- php四種回調寫法
- 守護進程程序常用數據結構
- swoole生命周期
- swoole_server中內存管理機制
- 使用jemalloc優化swoole內存分配性能
- Reactor、Worker、Task的關系
- Manager進程
- Swoole的實現
- Reactor線程
- 安裝擴展
- swoole-worker手冊
- swoole相關開源項目
- 寫在后面的話
- 版本更新記錄
- 4.0