>  기사  >  백엔드 개발  >  ThinkPHP에서 양식 토큰 오류 분석 및 해결

ThinkPHP에서 양식 토큰 오류 분석 및 해결

*文
*文원래의
2018-01-03 11:45:211721검색

ThinkPHP에서 양식 토큰 오류를 해결하는 방법은 무엇입니까? 이 글에서는 주로 ThinkPHP의 폼 토큰 오류와 해결 방법을 소개하고, thinkPHP 폼 토큰의 원리, 구성, 오류 원인 및 해당 해결 방법을 좀 더 자세히 분석합니다. 도움이 필요한 친구들이 참고하면 좋을 것 같아요.

자세한 내용은 다음과 같습니다.

프로젝트 개발 과정에서 데이터를 추가하고 편집할 때 시스템에서 표시되는 '양식 토큰 오류'가 가끔 발생했습니다. 처음에는 크게 신경 쓰지 않았습니다. QA가 오늘 오후에 버그 시스템에 이 문제를 언급했습니다. 시간이 좀 남아서 TP3.13의 소스 코드를 따라 읽어보니 전체 내용을 알 수 있었습니다.

프로젝트에서 양식 토큰을 활성화하려면 일반적으로 구성 파일에서 다음 구성을 수행해야 합니다.

// 是否开启令牌验证
'TOKEN_ON' => true,
// 令牌验证的表单隐藏字段名称
'TOKEN_NAME' => '__hash__',
//令牌哈希验证规则 默认为MD5
'TOKEN_TYPE' => 'md5',
//令牌验证出错后是否重置令牌 默认为true
'TOKEN_RESET' => true

데이터 편집을 예로 들면 일반적으로 서버에는 필드 필터링 규칙이 있는 모델과 데이터 감지가 있는 작업이 있습니다.

$table = D('table');
if(!$table->create()){
  exit($this->error($table->getError()));
}

이때 IDE에서 create()를 더블클릭하면 TP 프레임워크의 Model.class.php에서 create 메소드를 찾을 수 있습니다

/**
* 创建数据对象 但不保存到数据库
* @access public
* @param mixed $data 创建数据
* @param string $type 状态
* @return mixed
*/
public function create($data='',$type='') {
  ……省略……
  // 表单令牌验证
  if(!$this->autoCheckToken($data)) {
    $this->error = L('_TOKEN_ERROR_');
    return false;
  }
  ……省略……
}

코드를 보시면 이해가 되실 겁니다. autoCheckToken 메소드가 감지에 실패하면 오류가 보고되므로 이 메소드를 계속 추적하세요.

// 自动表单令牌验证
// TODO ajax无刷新多次提交暂不能满足
public function autoCheckToken($data) {
  // 支持使用token(false) 关闭令牌验证
  // 如果在Action写了D方法,但没有对应的Model文件,那么$this->options为空
  if(isset($this->options['token']) && !$this->options['token']) return true;
  if(C('TOKEN_ON')){
    $name  = C('TOKEN_NAME');
    if(!isset($data[$name]) || !isset($_SESSION[$name])) { // 令牌数据无效
      return false;
    }
    // 令牌验证
    list($key,$value) = explode('_',$data[$name]);
    if($value && $_SESSION[$name][$key] === $value) { // 防止重复提交
      unset($_SESSION[$name][$key]); // 验证完成销毁session
      return true;
    }
    // 开启TOKEN重置
    if(C('TOKEN_RESET')) unset($_SESSION[$name][$key]);
    return false;
  }
  return true;
}

이 코드를 읽고 나면 첫 번째 판단에 $_SESSION[$name]이 있음을 알 수 있습니다. 그러면 이 시션은 어디에 있습니까? 변수는 토큰을 생성하고 TokenBuildBehavior를 찾는 것부터 시작해야 합니다. .class.php 파일

// 创建表单令牌
private function buildToken() {
  $tokenName = C('TOKEN_NAME');
  $tokenType = C('TOKEN_TYPE');
  if(!isset($_SESSION[$tokenName])) {
    $_SESSION[$tokenName] = array();
  }
  // 标识当前页面唯一性
  $tokenKey  = md5($_SERVER['REQUEST_URI']);
  if(isset($_SESSION[$tokenName][$tokenKey])) {// 相同页面不重复生成session
    $tokenValue = $_SESSION[$tokenName][$tokenKey];
  }else{
    $tokenValue = $tokenType(microtime(TRUE));
    $_SESSION[$tokenName][$tokenKey]  = $tokenValue;
  }
  $token   = &#39;<input type="hidden" name="&#39;.$tokenName.&#39;" value="&#39;.$tokenKey.&#39;_&#39;.$tokenValue.&#39;" />&#39;;
  return $token;
}

이 코드는 TP가 양식을 켤 때 현재 URI의 TOKEN_NAME 및 md5를 사용하여 토큰 값을 생성하는 데 사용됩니다. 그런 다음 사용자가 양식을 제출하면 먼저 토큰이 세션에 존재하는지 확인하고 존재하지 않으면 false를 반환합니다. 일치하는 경우 양식 필드 TOKEN_NAME을 사용하여 확인합니다. 이 세션을 먼저(다음 번에 양식 토큰 오류 제출을 방지하기 위해) true를 반환하고, 그렇지 않으면 false를 반환합니다.

주제로 돌아가서, TP

1에서 양식을 제출할 때 토큰 오류가 발생할 수 있는 가능성은 두 가지뿐입니다. 토큰이 켜져 있으면 제출된 양식에 TOKEN_NAME 필드가 없거나 해당 세션이 없습니다( 현재 제출 양식 환경에서는 해당 세션이 생성되지 않습니다. 이는 주로 사용자가 제출한 후 사용자가 현재 페이지를 새로 고친 후 편집 페이지와 표시 페이지가 동일하기 때문입니다. method)

2. 세션 변수가 있는데, 전후 값이 다릅니다

저희 프로젝트에서 이런 오류가 발생하는 이유는 아래 구성을 보면 알 수 있습니다

return array (
  &#39;TOKEN_ON&#39; => &#39;false&#39;,
  &#39;TOKEN_NAME&#39; => &#39;__hash__&#39;,
  &#39;TOKEN_TYPE&#39; => &#39;md5&#39;,
  &#39;TOKEN_RESET&#39; => &#39;true&#39;,
  &#39;DB_FIELDTYPE_CHECK&#39; => &#39;true&#39;
);

false로 작성했어야 합니다. 부울값으로 했는데 어떤 영웅이 고의로 문자열로 false라고 썼는지는 모르겠지만, 그럼 판단할 때는 물론 폼 토큰을 여는 로직을 기준으로 하고, 프로젝트에서는 추가, 편집, 표시하는 방법은 모두 동일합니다. 검증 오류가 발생하면 일반 프로그램 처리 로직이 원래 인터페이스로 돌아가므로 지난 번과 동일한 양식이 됩니다. 예, 동일한 양식을 계속 제출하는 것은 반복 제출과 동일합니다. 양식 토큰 오류'가 보고됩니다.

관련 권장사항:

ThinkPHP의 동작 확장 및 플러그인에 대한 자세한 설명

ThinkPHP가 인증 코드를 생성하고 확인하는 방법에 대한 자세한 설명

thinkphp5 URL에 대한 자세한 설명 예 및 라우팅 기능

위 내용은 ThinkPHP에서 양식 토큰 오류 분석 및 해결의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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