기존 웹 개발 프로세스에서는 그래픽 인증 코드를 처리하는 것이 매우 간단합니다. 사용자가 백그라운드에서 이미지를 생성하고 인증 코드 내용을 삽입하기만 하면 됩니다. 양식을 제출하면 세션에서 생성됩니다. [1] 판결을 내리세요.
하지만 요즘에는 세션 측면에서 API 상호 작용과 무국적성을 점점 더 옹호하고 있지만 기본 구성은 지원되지 않지만 여전히 국가를 구할 수 있는 방법이 많이 있습니다.
API 개발에서는 프런트 엔드에 SessionID를 발급하고 PHP의 내장 메서드를 통해 이 모든 것을 달성할 수도 있습니다.
예를 들어, 요청에 X-Session-Id
가 포함되어 있고 비어 있지 않으면 이 세션이 이미 SessionID를 등록했다는 의미라는 이전 단락에 동의했습니다. 그렇지 않으면 SessionID가 공개됩니다. 응답 헤더 X-Session-Id
에 반환되면 이전 섹션에서 이 SessionID를 기록할 수 있습니다. 아래에서 간단히 구현해 보겠습니다. X-Session-Id
,且不为空时,表示这个会话已经注册过 SessionID ,否则就颁布一个 SessionID 并返回在 Response Header 中的 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();
上面基本实现了生成图片,前端需要根据 只需要再提交表单时,在 headers 中带上 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']);
上面使用 Session ,我们基本就实现了一个简单的验证,而且是基于 API 交互的,不依赖浏览器 cookie 。当我们需要一些复杂的比如共享 Session ,这些就不在本文的讨论范围了(其实现在也已经超纲了)
接下来的方法是无状态的,但是需要用到 Redis 。这里使用 PHPRedis 这个扩展来处理。
在大多数情况下,我们并不需要像上面使用 Session 那样来创建过多的 Session ,造成有一些资源浪费,当然,Session 可以做的不止这些,下面我们就用 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 ,虽然看着不咋地,但是他也实现了我们想要的,不过这个也不算是太好的方案,而且,还要考虑客户端字符串不够随机的情况,接下来我们改变一下方向,换成服务端签发。
刚刚的是基于客户端签发的实现,下面来提供另一种思路,但是大体上,这个是差不多的哈都。
同样是签发 Sign ,只不过这次由服务端来签发,然后将 Sign 通过 Header 发送给客户端,客户端需要先取到图片资源,注意这里返回的应该是一个合法的二进制流,然后从 header 中取出 Sign ,同时展示给用户。
// 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 的方式变了一下,但是,这样搞的话,前端同学可能就不爽了,他们要先获取这个资源和 headers 中的 X-Captcha-Sign
header('Access-Control-Expose-Headers: X-Captcha-Sign');위는 기본적으로 이미지 생성을 구현한 것입니다. 프런트 엔드에서는 양식을 제출할 때 헤더에
X-Session-ID
만 추가하면 됩니다. rrreee네, 확인해 보겠습니다. rrreee
좀 더 복잡해 보이고 심지어 Redis를 사용하기도 합니다. 보기에는 좋지 않지만 원하는 결과도 얻을 수 있지만 이는 그다지 좋은 솔루션이 아니며 클라이언트가 고려해야 할 사항입니다. 문자열이 충분히 무작위적이지 않다면 방향을 바꾸고 서버측 발행으로 전환해 보겠습니다.서버 측 발행 기반
지금 구현된 내용은 클라이언트 측 발행을 기반으로 하지만 일반적으로 거의 동일합니다. 이론적 원리Sign도 발급되지만 이번에는 서버에서 서명한 다음 클라이언트가 이미지 리소스
를 먼저 가져와야 합니다. 여기에 반환된 것은 합법적인 바이너리 스트림이어야 하며, 헤더에서 Sign을 꺼내 동시에 사용자에게 표시해야 합니다. 🎜rrreee🎜변화가 거의 없는 것 같고 Sign 생성 방식만 변경된 것 같습니다. 하지만 이렇게 하면 프론트엔드 학생들이 먼저 이 리소스와X-를 구해야 합니다. 헤더에 Captcha-Sign[참고 1] 이 글에서 언급한 Session은 기술적인 표준이며 우리가 종종 브라우저를 통해 자동으로 쿠키를 전달한다고 말하는 상호작용에는 Session이라는 특정 개념이 있습니다. 하지만 여기서는 SessionID Pass를 수동으로 구현했습니다. 항상 세션 "세션"의 문자 그대로의 번역 의미를 유지합니다. <p><span style='color: rgb(61, 70, 77); font-family: "Helvetica Neue", Helvetica, "PingFang SC", 微软雅黑, Tahoma, Arial, sans-serif; background-color: rgb(255, 255, 255);'>PHP 관련 기술 기사를 더 보려면 </span><a href="http://www.php.cn/php-weizijiaocheng.html" target="_self" style='margin: 0px; padding: 0px; color: rgb(146, 208, 80); font-family: "Helvetica Neue", Helvetica, "PingFang SC", 微软雅黑, Tahoma, Arial, sans-serif; white-space: normal; background-color: rgb(255, 255, 255);'><span style="margin: 0px; padding: 0px;">PHP 튜토리얼</span></a><span style='color: rgb(61, 70, 77); font-family: "Helvetica Neue", Helvetica, "PingFang SC", 微软雅黑, Tahoma, Arial, sans-serif; background-color: rgb(255, 255, 255);'> 열을 방문하세요. 배우다 ! </span></p>
위 내용은 API 상호 작용에서 이미지 확인 코드를 생성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!