本文主要讲解了在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/