ホームページ >バックエンド開発 >PHPの問題 >PHPでhttps双方向認証を実装する方法

PHPでhttps双方向認証を実装する方法

藏色散人
藏色散人オリジナル
2020-08-11 09:12:114593ブラウズ

php で https を実装する方法: まず openssl 構成を変更し、次に CA ルート証明書を作成し、証明書パスワードを 6 文字以上に設定し、次にサーバー証明書とクライアント証明書を作成し、最後にnginxを設定してphpを実行する テストをcurlするだけです。

PHPでhttps双方向認証を実装する方法

推奨: 「PHP ビデオ チュートリアル

php は https (tls/ssl) を 2 つ実装します。方法認証

通常、https を導入する場合、SSL 一方向認証に基づきます。つまり、クライアントがサーバーを認証する限り、サーバーはクライアントを認証する必要はありません。

ただし、銀行、金融、その他の分野など、より高度なセキュリティが必要な一部のシナリオでは、通常、クライアント認証が必要です。これにより、SSL の双方向認証が有効になります。

nginx の ssl_client_certificate パラメータではクライアント公開鍵を 1 つしか指定できないため、通信用のクライアントを追加する場合は、新しいサーバーを設定する必要があります。

n:1 モードは、CA のカスケード証明書モードを通じて実装されます。まず、CA ルートレベルの証明書のセットを自分で生成し、それを使用してセカンダリ証明書をクライアント証明書として生成します。

このとき、クライアント秘密鍵の署名は、対応するクライアント公開鍵だけでなく、ルート証明書の公開鍵によっても検証できます。

これを見ればわかると思います 操作方法を簡単に紹介します

1 準備作業

1.1 Opensslディレクトリの準備

概要状況 openssl の設定ファイルはすべてこのディレクトリ /etc/pki/tls にあります。したがって、次のようになります。

mkdir /etc/pki/ca_linvo
cd /etc/pki/ca_linvo
mkdir root server client newcerts
echo 01 > serial
echo 01 > crlnumber
touch index.txt

1.2 openssl 設定の準備

openssl 設定の変更

vi /etc/ pki/ tls/openssl.cnf

この文をコメントアウトして次の文に置き換えます

#default_ca      = CA_default
default_ca      = CA_linvo

[CA_default] の部分全体をコピーし、[CA_linvo]# の上の名前に変更します。

##内部の次のパラメータを変更します。

dir = /etc/pki/ca_linvo
certificate = $dir/root/ca.crt
private_key = $dir/root/ca.key

保存して終了

2 CA ルート証明書を作成します

生成key:openssl genrsa -out /etc/pki/ca_linvo/root/ca.key
生成csr:openssl req -new -key /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.csr
生成crt:openssl x509 -req -days 3650 -in /etc/pki/ca_linvo/root/ca.csr -signkey /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/root/ca.crt
生成crl:openssl ca -gencrl -out /etc/pki/ca_linvo/root/ca.crl -crldays 7

生成されたルート証明書ファイルはすべて /etc/ にあります。 pki/ ca_linvo/root/ ディレクトリの下

## 注: 証明書を作成する場合、Java keytool ツールにはその要件があるため、証明書のパスワードの長さを 6 文字以上にすることをお勧めします。

3 サーバー証明書の作成

生成key:openssl genrsa -out /etc/pki/ca_linvo/server/server.key
生成csr:openssl req -new -key /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.csr
生成crt:openssl ca -in /etc/pki/ca_linvo/server/server.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/server/server.crt -days 3650

手順:

1. ここで生成された crt は、先ほどの ca ルート証明書の下にあるカスケード証明書です。実際、サーバー証明書は主に構成に使用されます。通常の一方向 https なので、カスケード モードを使用せずに実行できます:

openssl rsa -in /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.key
openssl x509 -req -in /etc/pki/ca_linvo/server/server.csr -signkey /etc/pki/ca_linvo/server/server.key -out /etc/pki/ca_linvo/server/server.crt -days 3650

2. -days パラメーターは、必要に応じて証明書の有効期間を設定できます (デフォルトなど)。は 365 日です。

4 クライアント証明書の作成

生成key:openssl genrsa -des3 -out /etc/pki/ca_linvo/client/client.key 1024
生成csr:openssl req -new -key /etc/pki/ca_linvo/client/client.key -out /etc/pki/ca_linvo/client/client.csr
生成crt:openssl ca -in /etc/pki/ca_linvo/client/client.csr -cert /etc/pki/ca_linvo/root/ca.crt -keyfile /etc/pki/ca_linvo/root/ca.key -out /etc/pki/ca_linvo/client/client.crt -days 3650

注:

1. ここではカスケード証明書を使用する必要があり、この手順を繰り返して複数のクライアント証明書のセットを作成できます。

2. crt 生成時にこれが発生する可能性があります 次のエラーが報告されます:

openssl TXT_DB error number 2 failed to update database

操作についてはここを参照してください。

私は方法 1 を使用しています。これは、index.txt.attr で unique_subject = no

5 を使用して nginx を構成することです。

サーバー セグメントの主要な部分のみがリストされています。ここ:

ssl_certificate  /etc/pki/ca_linvo/server/server.crt;#server公钥
ssl_certificate_key  /etc/pki/ca_linvo/server/server.key;#server私钥
ssl_client_certificate   /etc/pki/ca_linvo/root/ca.crt;#根级证书公钥,用于验证各个二级client
ssl_verify_client on;

Nginx を再起動

6 テスト

6.1 ブラウザ テスト

双方向認証により、ブラウザ経由で https アドレスに直接アクセスすると、 400 Bad Request (必要な SSL 証明書が送信されなかった) が発生した場合は、クライアント証明書をローカル マシンにインストールする必要があります。

Windows にインストールされる証明書は、p12 形式とも呼ばれる pfx 形式である必要があります。生成方法は次のとおりです:

openssl pkcs12 -export -inkey /etc/pki/ca_linvo/client/client.key -in /etc/pki/ca_linvo/client/client.crt -out /etc/pki/ca_linvo/client/client.pfx

次に、Windows でそれをダブルクリックしてインストールします。インストール時に、証明書を生成する時間を入力するように求められます。パスワードを設定します。

インストールが成功したら、ブラウザを再起動し、URL を入力してアクセスします。ブラウザで証明書の選択を求められる場合があります。インストールした証明書を選択してください。

現時点では、一部のブラウザでは、証明書が信頼できない、アドレスが安全ではないなどのメッセージがユーザーに表示されます。これは、サーバー証明書が実際の権威ある CA 組織ではなく、独自に発行されているためです (通常は非常に高価です~)、無視してください。

6.2 PHPカールテスト

設定する必要がある主要なカールパラメータのみがここにリストされています:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书,不是CA机构颁布的也没关系  
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); // 检查证书中是否设置域名,如果不想验证也可设为0  
curl_setopt($ch, CURLOPT_VERBOSE, '1'); //debug模式,方便出错调试  
curl_setopt($ch, CURLOPT_SSLCERT, CLIENT_CRT); //client.crt文件路径,这里我用常量代替  
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, CRT_PWD); //client证书密码  
curl_setopt($ch, CURLOPT_SSLKEY, CLIENT_KEY); //client.key文件路径  
 
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:私钥存放路径
 
 
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;
}

検証が失敗し、次の情報がnginxに表示されます。エラー ログ

2017/06/05 17:45:07 [crit] 16084#0: *27458991 SSL_do_handshake() failed (SSL: error:04067084:rsa routines:RSA_EAY_PUBLIC_DECRYPT:data too large for modulus e
rror:1408807A:SSL routines:ssl3_get_cert_verify:bad rsa signature) while SSL handshaking, client: 116.255.208.194, server: 0.0.0.0:443

6.3 phpsoaptest

まず、クライアントの pem 形式の証明書を構築する必要があります。openssl コマンドを使用することもできますが、すでに crt とキーがあるため、手動でマージする必要があります。これも非常に簡単です:

新しいファイルを作成し、-----BEGIN CERTIFICATE----- と -----END CERTIFICATE--- の間に Base64 コンテンツ (これら 2 つの分割線を含む) をコピーします。 -- crt. で、キーの -----BEGIN RSA PRIVATE KEY----- と -----END RSA PRIVATE KEY----- の間の内容をコピーし、クライアントとして保存します。 .pem 。

実際、よりトラブルが少ない場合は、次のコマンドを使用して 2 つのファイルを直接マージできます。

cat /etc/pki/ca_linvo/client/client.crt /etc/pki/ca_linvo/client/client.key > /etc/pki/ca_linvo/client/client.pem

pem ファイルを使用すると、組み込みの SoapClient を使用できます。 php で呼び出します。コンストラクターは 2 番目のパラメータを設定する必要があります :

$header = array(          
    'local_cert' => CLIENT_PEM, //client.pem文件路径  
    'passphrase' => CRT_PWD //client证书密码  
    );  
$client = new SoapClient(FILE_WSDL, $header); //FILE_WSDL为要访问的https地址

前回のブログで、local_cert がリモート パスに設定されている場合、エラーが報告されると述べました。クライアント証明書は使用されていないようです。 wsdl を初めて取得するとき。wsdl はローカル ファイルとして保存する必要があります。Call;

ただし、今回のテストでは問題ありませんでした。ローカル ファイルとして保存する必要はありません。 、リモートで取得するだけです。

最初は前の証明書に問題があるのではないかと思ったのですが、以前の証明書セットを引き続き使用できます。これは非常に奇妙です~~~~~

以上がPHPでhttps双方向認証を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。