PHPCMS v 9二次開発_検証コードとSessionを組み合わせた開発

9370 ワード

本稿では,V 9にv 9を用いて認証コードを持参し,セッションを用いる必要がある場合の多様な問題の解決について説明する.問題があったり、もっと良い解決策があれば、教えてほしいです.
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'];

オリジナルセッションを使用して検証コードを検証する必要がある場合、検証コードはセッションから取り出せません.
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));
}    

解析の結果,セッションが取り出せないのは,v 9コードにcodeのセッションが格納されている場合にセッションが呼び出されるためである.mysqlクラス.
api/checkcode.php:
$session_storage = 'session_'.pc_base::load_config('system','session_storage');
pc_base::load_sys_class($session_storage);

二)、v 9 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");
    }
}
?>

このセッションの使用方法:
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のデータを格納する必要がある場合、配列のサイズは不定であり、v 9が持参したsession_を使用するとします.mysqlは本質的にsession値をデータベースに格納し、取得時にデータベースを読み出し、配列が格納されている場合、読み出したデータは「Array」文字列である.
研究の結果,ここには2つの解決策がある.
a、データベースのフィールドのタイプ、サイズを変更します(もともとvarcharタイプで、255文字しか保存できません).配列をjson文字列に変換し、session_を使用します.mysql方式で格納します.
b、session_の使用files方式はストレージから.
三)、v 9 session_files
ここで注意すべきは、検証コードとsessionの両方を使用でき、配列をsessionで格納できることを実現することである.(検証コードの再書き込みは推奨されません)
v 9では、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)}

この方式を用いてセッション読み出しセッションを格納する場合には、生PHPで使用するのと同様に、$_をそのまま使用するSESSION.この方法により、$_を読み出すことができるSESSION['code']値もsessionに配列を格納する問題を完璧に解決できる.
 
 
 
========================
by llicat
転載は出典を明記する必要がある:http://www.cnblogs.com/llicat/