本文主要讲解了在V9中使用v9自带验证码并且需要使用session的情况下,多种问题的解决。:)。如有问题或者更好的解决办法,希望不吝赐教。

1、前端调用验证码

pc_base::load_sys_class('form', '', 0);

{form::checkcode('code_img', '4', '14', 120, 26)}
 
2、管理端验证码验证
$code = isset($_POST['code']) && trim($_POST['code']) ? trim($_POST['code']) : exit(format_ajax_out_json('-1', '请输入验证码'));
if ($_SESSION['code'] != strtolower($code)) {
exit(format_ajax_out_json('-1', "验证码错误!"));
}

3、结合验证码Session的使用

一)、PHP原生Session

session_start();
//注意$output['data']['area']数据为数组,其他为字符串,原生session能够存储数组
$_SESSION['area'] = $output['data']['area'];
$_SESSION['yhid'] = $output['data']['yhid'];

在需要使用原生session且验证验证码时,验证码从session中是取不出来的:

if (isset($_GET['dosubmit'])) {
  session_start();
  $code = isset($_POST['code']) && trim($_POST['code']) ? trim($_POST['code']) : exit(format_ajax_out_json('-1', '请输入验证码'));
  if ($_SESSION['code'] != strtolower($code)) {
  exit(format_ajax_out_json('-1', "验证码错误!"));
}
  //-------------------------省略中间代码-------------------------------
  //添加session   //注意$output['data']['area']数据为数组,其他为字符串,原生session能够存储数组
  $_SESSION['area'] = $output['data']['area'];
  $_SESSION['yhid'] = $output['data']['yhid'];   exit(format_ajax_out_json($output['statusCode'], $output));
}

经过分析,session取不出来的原因,是因为v9代码中,存储code的session时,调用的是session_mysql类。

api/checkcode.php:

$session_storage = 'session_'.pc_base::load_config('system','session_storage');
pc_base::load_sys_class($session_storage);

二)、v9  session_mysql

session_mysql.class.php:(v9)

<?php
/**
* session mysql 数据库存储类
*
* @copyright (C) 2005-2010 PHPCMS
* @license http://www.phpcms.cn/license/
* @lastmodify 2010-6-8
*/
class session_mysql {
var $lifetime = 1800;
var $db;
var $table;
/**
* 构造函数
*
*/
public function __construct() {
$this->db = pc_base::load_model('session_model');
$this->lifetime = pc_base::load_config('system','session_ttl');
session_set_save_handler(array(&$this,'open'), array(&$this,'close'), array(&$this,'read'), array(&$this,'write'), array(&$this,'destroy'), array(&$this,'gc'));
session_start();
}
/**
* session_set_save_handler open方法
* @param $save_path
* @param $session_name
* @return true
*/
public function open($save_path, $session_name) { return true;
}
/**
* session_set_save_handler close方法
* @return bool
*/
public function close() {
return $this->gc($this->lifetime);
}
/**
* 读取session_id
* session_set_save_handler read方法
* @return string 读取session_id
*/
public function read($id) {
$r = $this->db->get_one(array('sessionid'=>$id), 'data');
return $r ? $r['data'] : '';
}
/**
* 写入session_id 的值
*
* @param $id session
* @param $data 值
* @return mixed query 执行结果
*/
public function write($id, $data) {
$uid = isset($_SESSION['userid']) ? $_SESSION['userid'] : 0;
$roleid = isset($_SESSION['roleid']) ? $_SESSION['roleid'] : 0;
$groupid = isset($_SESSION['groupid']) ? $_SESSION['groupid'] : 0;
$m = defined('ROUTE_M') ? ROUTE_M : '';
$c = defined('ROUTE_C') ? ROUTE_C : '';
$a = defined('ROUTE_A') ? ROUTE_A : '';
if(strlen($data) > 255) $data = '';
$ip = ip();
$sessiondata = array(
'sessionid'=>$id,
'userid'=>$uid,
'ip'=>$ip,
'lastvisit'=>SYS_TIME,
'roleid'=>$roleid,
'groupid'=>$groupid,
'm'=>$m,
'c'=>$c,
'a'=>$a,
'data'=>$data,
);
return $this->db->insert($sessiondata, 1, 1);
}
/**
* 删除指定的session_id
*
* @param $id session
* @return bool
*/
public function destroy($id) {
return $this->db->delete(array('sessionid'=>$id));
}
/**
* 删除过期的 session
*
* @param $maxlifetime 存活期时间
* @return bool
*/
public function gc($maxlifetime) {
$expiretime = SYS_TIME - $maxlifetime;
return $this->db->delete("`lastvisit`<$expiretime");
}
}
?>

该session的使用方式:

private function _session_start() {
$session_storage = 'session_'.pc_base::load_config('system','session_storage');
$this->todo_session = pc_base::load_sys_class($session_storage);
} public function dlsLogin() {
$this->_session_start();   if (isset($_GET['dosubmit'])) {
    $code = isset($_POST['code']) && trim($_POST['code']) ? trim($_POST['code']) : exit(format_ajax_out_json('-1', '请输入验证码'));
    if ($_SESSION['code'] != strtolower($code)) {
      exit(format_ajax_out_json('-1', "验证码错误!"));
    }
  
  //-------------------------省略中间代码-------------------------------
  
  //注意$output['data']['area']数据为数组,其他为字符串,原生session能够存储数组,而session_mysql方法不能存储数组。
      $this->todo_session->write('area',$output['data']['area']);
  $this->todo_session->write('yhid',$output['data']['yhid']);
     exit(format_ajax_out_json($output['statusCode'], $output));
  }
}

  使用该session方式能很好的使用验证码+需要写入session的数据,但是该方法有个弊端。则:无法在session中存储数组。假设,你需要存入session的数据时数组,且数组的大小是不定的,而使用v9自带的session_mysql其实质是将session值存入数据库,在取的时候读取数据库,如果存一个数组在其中,读出来的数据则是一个"Array"字符串。

  经过研究,这里有两种解决方案。

  a、将数据库的字段的类型、大小改变(原本为varchar类型,且只能存储255个字符)。并将数组转换成一个json字符串,并使用session_mysql的方式存储。

  b、使用session_files方式从存储。

三)、v9  session_files

  这里需要注意的是,我们需要实现的目的是既能使用验证码又能使用session,且能用session存储数组。(不建议重新写一套验证码)

  v9  中,除了用数据库存储session还能用文件的方式。

session_files.class.php:

<?php
class session_files {
function __construct() {
$path = pc_base::load_config('system', 'session_n') > 0 ? pc_base::load_config('system', 'session_n').';'.pc_base::load_config('system', 'session_savepath') : pc_base::load_config('system', 'session_savepath');
ini_set('session.save_handler', 'files');
session_save_path($path);
session_start();
}
}
?>

  由于要使用验证码,这里需要重新写一个api中的checkcode.php并且在form.class.php中添加一个方法。

新建api/checkcode_files.php

<?php
defined('IN_PHPCMS') or exit('No permission resources.'); pc_base::load_sys_class('session_files');
$checkcode = pc_base::load_sys_class('checkcode');
//之后代码省略------------------

form.class.php添加方法

//验证码 session_file存储方式
public static function checkcode_file($id = 'checkcode',$code_len = 4, $font_size = 20, $width = 130, $height = 50, $font = '', $font_color = '', $background = '') {
  return "<img id='$id' onclick='this.src=this.src+\"&\"+Math.random()' src='".SITE_PROTOCOL.SITE_URL.WEB_PATH."api.php?op=checkcode_file&code_len=$code_len&font_size=$font_size&width=$width&height=$height&font_color=".urlencode($font_color)."&background=".urlencode($background)."'>";
}

前端调用:

{form::checkcode_file('code_img', '4', '14', 120, 26)}

  使用该方式在存储session读取session时与原生PHP中使用一样,直接使用$_SESSION。使用该方法,既能读出$_SESSION['code']值也能完美的解决在session中存储数组的问题。

========================

by llicat

转载需注明出处:http://www.cnblogs.com/llicat/

PHPCMS v9 二次开发_验证码结合Session开发的更多相关文章

  1. PHPCMS V9二次开发便捷自定义后台入口文件夹

    phpcms v9二次开发便捷自定义后台入口文件夹 最新发布的phpcms v9由于采用了mvc的设计模式,所以它的后台访问地址是固定的,虽然可以通过修改路由配置文件来实现修改,但每次都修改路由配置文 ...

  2. phpcms v9二次开发之模型类的应用(1)

    在<phpcms二次开发之模型类model.class.php>中讲到了模型类的建立方法,接下来我讲一下模型类的应用.      前段时间我基于phpcms v9开发了一个足球网.足球网是 ...

  3. phpcms v9二次开发之模型类的应用(2)

    二.模型操作方法select()--查询语句         //查询级别管理列表信息    public function levellists() { $lelists = $this->l ...

  4. phpcms v9二次开发之数据模型类

    系统模型类:model.class.php数据模型类的位置:/phpcms/libs/classes phpcms v9二次开发中,我们要经常需要对模块的数据表进行查询.添加.修改和删除数据等操作,所 ...

  5. phpcms v9二次开发笔记

    phpcms是基于MVC结构的. 安装: 下载phpcms_v9.5.9_UTF8.zip:新建目录phpcms,将压缩包里install_package目录下所有文件复制到phpcms目录.浏览器输 ...

  6. phpcms V9 二次开发------(获取点击数详解)

    关于phpcms V9的点击数的使用应该有不少数是直接调用网上搜索到的代码,但是对于一些想要深入研究开发的人来说,看到网上的代码后更是不解,本人这几天看了看,了解了一些东西,在这里写出来分享一下,首先 ...

  7. PHPCMS V9二次开发]自定义字段模型-文本组

    phpcms v9,我们在做类似于酒店房型等类型的时候,需要用到文本组字段模型,但phpcms并未提供该模型.如下图所示效果: 展示效果如下: 步骤/方法 打开phpcms\modules\conte ...

  8. PHPCMS V9 二次开发常用代码集

    0:调用最新文章,带所在版块 {pc:get sql="SELECT a.title, a.catid, b.catid, b.catname, a.url as turl ,b.url a ...

  9. phpcms v9 二次开发 - 自己添加源文件

    一.在根目录添加入口文件, 我现在要在根目录添加一个文件名为test.php 这样一个文件,为了调用系统的公用类和函数,必须加入一下包含文件 test.php代码如下 <?phpdefine(' ...

随机推荐

  1. qt——简单程序一步步来

    最简单的程序c1 #include "test.h" #include <QtGui/QApplication> #include <qapplication.h ...

  2. umlの交互图

    版权声明:本文为博主原创文章,若要转载请注明出处!^_^ https://blog.csdn.net/u010892841/article/details/24920155 前面介绍了uml的非常多种 ...

  3. 第一个Shader程序

    fx文件: float4x4 matWorld; float Time=1.0f; struct VS_OUTPUT { float4 Pos :POSITION; float4 Color :COL ...

  4. sqlnet.ora的作用

    sqlnet.ora的作用 1.限制客户端访问(如指定客户端域为不允许访问) 2.指定命名方法(local naming,directory nameing...)的优先级 3.启用日志及跟踪(log ...

  5. python3 捕捉代码行出错的小程序

    下面主要使用的是: try .. except .. else .. finally ...,用的是 traceback 这个第三方模块. import traceback #捕捉哪行代码报错 def ...

  6. AtCoder Beginner Contest 114 Solution

    A 753 Solved. #include <bits/stdc++.h> using namespace std; ]; int main() { mp[] = mp[] = mp[] ...

  7. Git冲突:commit your changes or stash them before you can merge. 解决办法

    用git pull来更新代码的时候,遇到了下面的问题: 1 2 3 4 error: Your local changes to the following files would be overwr ...

  8. JS的 instanceof 方法

    http://www.cnblogs.com/jasonxuli/p/6769282.html 这是 2014-12-10 发在 iteye 上的文章 今天突然想起js的原型继承模型和相关的proto ...

  9. AOP Schema配置

    AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入封装.继承和 ...

  10. tp5.1 Env使用

    5.1版本取消了所有的系统常量,原来的系统路径变量改为使用Env类获取(需要引入think\facade\Env) echo "app_path=========".Env::ge ...