>  기사  >  백엔드 개발  >  API 상호 작용에서 이미지 확인 코드를 생성하는 방법

API 상호 작용에서 이미지 확인 코드를 생성하는 방법

步履不停
步履不停원래의
2019-06-18 16:20:033319검색

API 상호 작용에서 이미지 확인 코드를 생성하는 방법

머리말

기존 웹 개발 프로세스에서는 그래픽 인증 코드를 처리하는 것이 매우 간단합니다. 사용자가 백그라운드에서 이미지를 생성하고 인증 코드 내용을 삽입하기만 하면 됩니다. 양식을 제출하면 세션에서 생성됩니다. [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

위 세션을 사용하여 기본적으로 API 상호 작용을 기반으로 하고 브라우저 쿠키에 의존하지 않는 간단한 확인을 구현했습니다. 공유 세션과 같이 복잡한 것이 필요한 경우 이는 이 기사의 범위를 벗어납니다(사실 지금은 범위를 벗어났습니다)

클라이언트 활성 서명 기반

다음 방법은 상태 비저장이지만 Redis를 사용해야 합니다. . 이는 PHPRedis 확장을 사용하여 처리됩니다.

대부분의 경우 위의 Session을 사용하는 것처럼 너무 많은 Session을 생성할 필요가 없으므로 리소스가 낭비될 수 있습니다. 물론 Redis를 사용하여 클라이언트를 적극적으로 만들어 보겠습니다. 에 대한 이미지 인증 코드를 발급합니다.

이론적 원리

클라이언트는 로컬에서 임의의 문자열을 생성한 다음 이를 주소 뒤에 연결하여 확인 코드를 얻습니다. 백엔드는 클라이언트에서 생성된 임의의 문자열을 가로채서 이를 확인 자격 증명으로 사용하여 Redis에 넣습니다. 그런 다음 클라이언트 제출 시 확인을 위해 이전에 생성된 임의의 문자열을 가져와야 합니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.