従来の Web 開発プロセスでは、グラフィカルな検証コードの処理は非常に簡単で、背景にランダムな文字列を含む画像を生成し、追加するだけで済みます。認証コードの内容をSessionに入れるだけで、ユーザーがフォームを送信する際にSession[1]から判定を取り出します。
しかし、現在では、API インタラクションとステートレス性がますます重視されており、セッション領域では、デフォルト構成はサポートされていませんが、国を救う方法はまだたくさんあります。
API 開発では、SessionID をフロントエンドに発行し、PHP の組み込みメソッドを通じてこれらすべてを実現することもできます。
たとえば、前の段落で、リクエストに XX-Session-Id
が含まれており、空でない場合は、このセッションがすでに SessionID を登録していることを意味することに同意しました。それ以外の場合、SessionID は発行され、ヘッダーのレスポンス X-Session-Id
で返されると、前のセクションでこの SessionID を記録できるようになります。以下で簡単に実装してみましょう。
// code_session.php session_start(); // 这里假设已经通过 Header 获取到了 SessionID,并保存到了 $sessionId 变量中。 // 当 SessionID 不存在,或者 为空 则创建新的 SessionID 。 if(!isset($sessionId) || empty($sessionId)){ $sessionId = session_create_id(); // 因为前台还没有 SessionID ,所以下发一个,通知前端保存。 header('X-Session-Id: '.$sessionId); } // 设置当前会话的 SessionID 。 session_id($sessionId); // 这里我们就可以自由的读写 Session 了。 // 生成验证码 $code = mt_rand(1e3 ,1e4-1); // create_image 请自行实现 或者使用现有的图形验证码库生成。 $image = create_image($code); // 存储进去 Session $_SESSION['code'] = $code; // 输出一张图片 $image->output();
上記は基本的に画像の生成を実装しています。フロントエンドはフォーム送信時にヘッダーに X-Session-ID
を追加するだけです。
// code_session_validate.php session_start(); // 这里假设已经通过 Header 获取到了 SessionID,并保存到了 $sessionId 变量中。 // 当 SessionID 不存在,或者 为空 则创建新的 SessionID 。 if( !isset($sessionId) || empty($sessionId) || !isset($_POST['code']) || empty($_POST['code']) ){ // 因为没有提交 SessionID 过来 这个肯定就是不成立的了,所以直接终止即可。 exit; } // 设置当前会话的 SessionID 。 session_id($sessionId); if($_POST['code']!=$_SESSION['code']){ // 验证码错误啦 exit; } // 验证通过了就删掉 code, unset($_SESSION['code']);
上記のセッションを使用して、基本的に API インタラクションに基づき、ブラウザーの Cookie に依存しない単純な検証を実装しました。セッションの共有など、複雑な処理が必要な場合は、この記事の範囲を超えています (実際、現在は範囲を超えています)
次このメソッドはステートフルではありませんが、Redis の使用が必要です。これは、PHPRedis 拡張機能を使用して処理されます。
ほとんどの場合、上記のセッションを使用する場合のように、あまりにも多くのセッションを作成する必要はありません。その結果、リソースが浪費されます。もちろん、セッションはそれ以上のことを行うことができます。以下では、Redis を使用してそれを実行しましょう。 クライアントは積極的に
のイメージ検証コードを発行します。
クライアントはランダムな文字列をローカルで生成し、それをアドレスの後ろでつなぎ合わせて検証コードを取得します。バックエンドはクライアントによって生成されたランダムな文字列をインターセプトし、それをRedis を入力し、それをクライアントに送信するときに、検証のために以前に生成されたランダムな文字列を持ってくる必要があります。
// code_client.php $salt = 'wertyujkdbaskndasda'; if(!isset($_GET['sign'])){ // 客户端没有提供签名,停止执行 exit; } // 用户传来的一切数据都是不可靠的,我们需要对其加盐后执行 md5 $sign = md5($_GET['sign'].$salt); // 拼接上签名作为 Redis 的 key $key = 'code:'.$sign; // 连接 Redis $cache = new \Redis(); // 生成验证码 $code = mt_rand(1e3,1e4-1); // 保存验证码到 Redis 并设置2分钟的有效期。 if($cache->exists($key)){ // 这个 Key 已经被占用了,这里先停止。 exit; } $cache->set($key,$code,60*2); // 创建图片并返回 $image = create_image($code); $image->output();
わかりました、確認してみましょう。
// code_client_validate.php $salt = 'wertyujkdbaskndasda'; if( !isset($_POST['sign']) || !isset($_POST['code']) // 没有提交验证码过来。 || !empty($_POST['code']) ){ // 客户端没有提供签名,停止执行 exit; } // 用户传来的一切数据都是不可靠的,我们需要对其加盐后执行 md5 $sign = md5($_POST['sign'].$salt); // 拼接上签名作为 Redis 的 key $key = 'code:'.$sign; // 连接 Redis $cache = new \Redis(); if(!$cache->exists($key)){ // 根本没有这个 key eixt; } if($cache->get($key)!=$_POST['code']){ // 验证码错误 } // 验证通过了就删除 $cache->del($key);
もう少し複雑なようで、Redis も使用されています。見た目は良くありませんが、必要なことは実現できますが、これはあまり良い解決策ではありません。クライアント文字列が十分にランダムではないことも考慮する必要があるため、次に方向を変えてサーバー側の発行に切り替えます。
今説明したことは、クライアント側の発行の実装に基づいています。ここでは別のアイデアを示しますが、一般的にはほぼ同じです。
署名の署名にも同じことが当てはまりますが、今回はサーバーによって署名され、署名はヘッダーを通じてクライアントに送信されます。まず image resource# を取得します。##、ここで返されるものは正当なバイナリ ストリームである必要があることに注意してください。その後、ヘッダーから署名を取り出してユーザーに表示します。
// code_server.php $cache = new \Redis(); $salt = 'wertyujkdbaskndasda'; function generateSign(){ global $cache,$salt; $sign = md5(mt_rand().$salt); // 拼接上签名作为 Redis 的 key $key = 'code:'.$sign; if($cache->exists($key)){ // 是的 你么有看错,就是如果生成的 Sign 已存在,就进行递归,直到生成出一个不存在的。 return generateSign(); } return $key; } // 连接 Redis $key = generateSign(); // 生成验证码 $code = mt_rand(1e3,1e4-1); // 保存验证码到 Redis 并设置2分钟的有效期。 $cache->set($key,$code,60*2); // 创建图片并返回 $image = create_image($code); // 哈哈 要剃掉前缀哟 header('X-Captcha-Sign: ' . str_replace('code:','',$key)); $image->output();Sign の生成方法が変わっただけで、ほとんど変更がないように見えますが、これを行うとフロントエンドの学生が動揺する可能性があります。最初にこのリソースを取得し、
X- ヘッダーに Captcha-Sign それからインターフェイスに表示します もちろん、結果を直接 Base64 化することも、バイナリ ストリームを直接使用してビットマップ表示を生成することもできます。検証方法は上記で直接使用できます。
Access-Control-Expose-Headers を設定する必要もあります。 - HTTP | MDN、そうでない場合、ajax はカスタマイズされた応答ヘッダーを取得できません。 。
header('Access-Control-Expose-Headers: X-Captcha-Sign');概要これら 3 つのソリューションを確認すると、基本的には私たちのニーズを満たすことができます。別のソリューションを考えついた人もいるかもしれません。 json インターフェース名を指定し、バックグラウンドで画像を生成して保存し、URL を返してフロントエンドに署名します。これは問題ありませんが、この方法ではリソースをあまり制御できず、ある程度の無駄が発生します。リソース。ここではわかりません。このオプションを検討してください。 記事内で言及されている知識の一部は、基礎知識の応用です。記事内のコードは、記事執筆時に直接入力したものです。誤字や論理的な誤りがある場合は、お気軽にご指摘ください。 。 この記事で使用されている Redis は、PHPRedis 拡張機能です。検証コードイメージの生成については、
gregwar/captcha - Packagist を使用できます。
上記は私の個人的な理解の一部です。より良い解決策がある場合は、共有してください。
リファレンス[注1] この記事で言及しているセッションは技術標準であり、一定の概念はありますが、よく言われるブラウザによるCookieの自動転送とは異なり、ここではSessionIDの転送を手動で実装するだけです。ただし、セッション「セッション」の文字通りの翻訳セマンティクスは常に維持されます。
PHP 関連の技術記事の詳細については、PHP チュートリアル 列にアクセスして学習してください。
以上がAPI インタラクションで画像検証コードを作成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。