441 lines
13 KiB
PHP
441 lines
13 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* Licensed to Jasig under one or more contributor license
|
||
|
* agreements. See the NOTICE file distributed with this work for
|
||
|
* additional information regarding copyright ownership.
|
||
|
*
|
||
|
* Jasig licenses this file to you under the Apache License,
|
||
|
* Version 2.0 (the "License"); you may not use this file except in
|
||
|
* compliance with the License. You may obtain a copy of the License at:
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
* PHP Version 5
|
||
|
*
|
||
|
* @file CAS/PGTStorage/Db.php
|
||
|
* @category Authentication
|
||
|
* @package PhpCAS
|
||
|
* @author Daniel Frett <daniel.frett@gmail.com>
|
||
|
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||
|
* @link https://wiki.jasig.org/display/CASC/phpCAS
|
||
|
*/
|
||
|
|
||
|
define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts');
|
||
|
|
||
|
/**
|
||
|
* Basic class for PGT database storage
|
||
|
* The CAS_PGTStorage_Db class is a class for PGT database storage.
|
||
|
*
|
||
|
* @class CAS_PGTStorage_Db
|
||
|
* @category Authentication
|
||
|
* @package PhpCAS
|
||
|
* @author Daniel Frett <daniel.frett@gmail.com>
|
||
|
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||
|
* @link https://wiki.jasig.org/display/CASC/phpCAS
|
||
|
*
|
||
|
* @ingroup internalPGTStorageDb
|
||
|
*/
|
||
|
|
||
|
class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage
|
||
|
{
|
||
|
/**
|
||
|
* @addtogroup internalCAS_PGTStorageDb
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* the PDO object to use for database interactions
|
||
|
*/
|
||
|
private $_pdo;
|
||
|
|
||
|
/**
|
||
|
* This method returns the PDO object to use for database interactions.
|
||
|
*
|
||
|
* @return PDO object
|
||
|
*/
|
||
|
private function _getPdo()
|
||
|
{
|
||
|
return $this->_pdo;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* database connection options to use when creating a new PDO object
|
||
|
*/
|
||
|
private $_dsn;
|
||
|
private $_username;
|
||
|
private $_password;
|
||
|
private $_driver_options;
|
||
|
|
||
|
/**
|
||
|
* @var string the table to use for storing/retrieving pgt's
|
||
|
*/
|
||
|
private $_table;
|
||
|
|
||
|
/**
|
||
|
* This method returns the table to use when storing/retrieving PGT's
|
||
|
*
|
||
|
* @return string the name of the pgt storage table.
|
||
|
*/
|
||
|
private function _getTable()
|
||
|
{
|
||
|
return $this->_table;
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// DEBUGGING
|
||
|
// ########################################################################
|
||
|
|
||
|
/**
|
||
|
* This method returns an informational string giving the type of storage
|
||
|
* used by the object (used for debugging purposes).
|
||
|
*
|
||
|
* @return string an informational string.
|
||
|
*/
|
||
|
public function getStorageType()
|
||
|
{
|
||
|
return "db";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method returns an informational string giving informations on the
|
||
|
* parameters of the storage.(used for debugging purposes).
|
||
|
*
|
||
|
* @return string an informational string.
|
||
|
* @public
|
||
|
*/
|
||
|
public function getStorageInfo()
|
||
|
{
|
||
|
return 'table=`'.$this->_getTable().'\'';
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// CONSTRUCTOR
|
||
|
// ########################################################################
|
||
|
|
||
|
/**
|
||
|
* The class constructor.
|
||
|
*
|
||
|
* @param CAS_Client $cas_parent the CAS_Client instance that creates
|
||
|
* the object.
|
||
|
* @param string $dsn_or_pdo a dsn string to use for creating a PDO
|
||
|
* object or a PDO object
|
||
|
* @param string $username the username to use when connecting to
|
||
|
* the database
|
||
|
* @param string $password the password to use when connecting to
|
||
|
* the database
|
||
|
* @param string $table the table to use for storing and
|
||
|
* retrieving PGT's
|
||
|
* @param string $driver_options any driver options to use when
|
||
|
* connecting to the database
|
||
|
*/
|
||
|
public function __construct(
|
||
|
$cas_parent, $dsn_or_pdo, $username='', $password='', $table='',
|
||
|
$driver_options=null
|
||
|
) {
|
||
|
phpCAS::traceBegin();
|
||
|
// call the ancestor's constructor
|
||
|
parent::__construct($cas_parent);
|
||
|
|
||
|
// set default values
|
||
|
if ( empty($table) ) {
|
||
|
$table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE;
|
||
|
}
|
||
|
if ( !is_array($driver_options) ) {
|
||
|
$driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
|
||
|
}
|
||
|
|
||
|
// store the specified parameters
|
||
|
if ($dsn_or_pdo instanceof PDO) {
|
||
|
$this->_pdo = $dsn_or_pdo;
|
||
|
} else {
|
||
|
$this->_dsn = $dsn_or_pdo;
|
||
|
$this->_username = $username;
|
||
|
$this->_password = $password;
|
||
|
$this->_driver_options = $driver_options;
|
||
|
}
|
||
|
|
||
|
// store the table name
|
||
|
$this->_table = $table;
|
||
|
|
||
|
phpCAS::traceEnd();
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// INITIALIZATION
|
||
|
// ########################################################################
|
||
|
|
||
|
/**
|
||
|
* This method is used to initialize the storage. Halts on error.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function init()
|
||
|
{
|
||
|
phpCAS::traceBegin();
|
||
|
// if the storage has already been initialized, return immediatly
|
||
|
if ($this->isInitialized()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// initialize the base object
|
||
|
parent::init();
|
||
|
|
||
|
// create the PDO object if it doesn't exist already
|
||
|
if (!($this->_pdo instanceof PDO)) {
|
||
|
try {
|
||
|
$this->_pdo = new PDO(
|
||
|
$this->_dsn, $this->_username, $this->_password,
|
||
|
$this->_driver_options
|
||
|
);
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
phpCAS::error('Database connection error: ' . $e->getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
phpCAS::traceEnd();
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// PDO database interaction
|
||
|
// ########################################################################
|
||
|
|
||
|
/**
|
||
|
* attribute that stores the previous error mode for the PDO handle while
|
||
|
* processing a transaction
|
||
|
*/
|
||
|
private $_errMode;
|
||
|
|
||
|
/**
|
||
|
* This method will enable the Exception error mode on the PDO object
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function _setErrorMode()
|
||
|
{
|
||
|
// get PDO object and enable exception error mode
|
||
|
$pdo = $this->_getPdo();
|
||
|
$this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE);
|
||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* this method will reset the error mode on the PDO object
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
private function _resetErrorMode()
|
||
|
{
|
||
|
// get PDO object and reset the error mode to what it was originally
|
||
|
$pdo = $this->_getPdo();
|
||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode);
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// database queries
|
||
|
// ########################################################################
|
||
|
// these queries are potentially unsafe because the person using this library
|
||
|
// can set the table to use, but there is no reliable way to escape SQL
|
||
|
// fieldnames in PDO yet
|
||
|
|
||
|
/**
|
||
|
* This method returns the query used to create a pgt storage table
|
||
|
*
|
||
|
* @return string the create table SQL, no bind params in query
|
||
|
*/
|
||
|
protected function createTableSql()
|
||
|
{
|
||
|
return 'CREATE TABLE ' . $this->_getTable()
|
||
|
. ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method returns the query used to store a pgt
|
||
|
*
|
||
|
* @return string the store PGT SQL, :pgt and :pgt_iou are the bind params contained
|
||
|
* in the query
|
||
|
*/
|
||
|
protected function storePgtSql()
|
||
|
{
|
||
|
return 'INSERT INTO ' . $this->_getTable()
|
||
|
. ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method returns the query used to retrieve a pgt. the first column
|
||
|
* of the first row should contain the pgt
|
||
|
*
|
||
|
* @return string the retrieve PGT SQL, :pgt_iou is the only bind param contained
|
||
|
* in the query
|
||
|
*/
|
||
|
protected function retrievePgtSql()
|
||
|
{
|
||
|
return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method returns the query used to delete a pgt.
|
||
|
*
|
||
|
* @return string the delete PGT SQL, :pgt_iou is the only bind param contained in
|
||
|
* the query
|
||
|
*/
|
||
|
protected function deletePgtSql()
|
||
|
{
|
||
|
return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
|
||
|
}
|
||
|
|
||
|
// ########################################################################
|
||
|
// PGT I/O
|
||
|
// ########################################################################
|
||
|
|
||
|
/**
|
||
|
* This method creates the database table used to store pgt's and pgtiou's
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function createTable()
|
||
|
{
|
||
|
phpCAS::traceBegin();
|
||
|
|
||
|
// initialize this PGTStorage object if it hasn't been initialized yet
|
||
|
if ( !$this->isInitialized() ) {
|
||
|
$this->init();
|
||
|
}
|
||
|
|
||
|
// initialize the PDO object for this method
|
||
|
$pdo = $this->_getPdo();
|
||
|
$this->_setErrorMode();
|
||
|
|
||
|
try {
|
||
|
$pdo->beginTransaction();
|
||
|
|
||
|
$query = $pdo->query($this->createTableSQL());
|
||
|
$query->closeCursor();
|
||
|
|
||
|
$pdo->commit();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
// attempt rolling back the transaction before throwing a phpCAS error
|
||
|
try {
|
||
|
$pdo->rollBack();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
}
|
||
|
phpCAS::error('error creating PGT storage table: ' . $e->getMessage());
|
||
|
}
|
||
|
|
||
|
// reset the PDO object
|
||
|
$this->_resetErrorMode();
|
||
|
|
||
|
phpCAS::traceEnd();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method stores a PGT and its corresponding PGT Iou in the database.
|
||
|
* Echoes a warning on error.
|
||
|
*
|
||
|
* @param string $pgt the PGT
|
||
|
* @param string $pgt_iou the PGT iou
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function write($pgt, $pgt_iou)
|
||
|
{
|
||
|
phpCAS::traceBegin();
|
||
|
|
||
|
// initialize the PDO object for this method
|
||
|
$pdo = $this->_getPdo();
|
||
|
$this->_setErrorMode();
|
||
|
|
||
|
try {
|
||
|
$pdo->beginTransaction();
|
||
|
|
||
|
$query = $pdo->prepare($this->storePgtSql());
|
||
|
$query->bindValue(':pgt', $pgt, PDO::PARAM_STR);
|
||
|
$query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
|
||
|
$query->execute();
|
||
|
$query->closeCursor();
|
||
|
|
||
|
$pdo->commit();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
// attempt rolling back the transaction before throwing a phpCAS error
|
||
|
try {
|
||
|
$pdo->rollBack();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
}
|
||
|
phpCAS::error('error writing PGT to database: ' . $e->getMessage());
|
||
|
}
|
||
|
|
||
|
// reset the PDO object
|
||
|
$this->_resetErrorMode();
|
||
|
|
||
|
phpCAS::traceEnd();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This method reads a PGT corresponding to a PGT Iou and deletes the
|
||
|
* corresponding db entry.
|
||
|
*
|
||
|
* @param string $pgt_iou the PGT iou
|
||
|
*
|
||
|
* @return string|false the corresponding PGT, or FALSE on error
|
||
|
*/
|
||
|
public function read($pgt_iou)
|
||
|
{
|
||
|
phpCAS::traceBegin();
|
||
|
$pgt = false;
|
||
|
|
||
|
// initialize the PDO object for this method
|
||
|
$pdo = $this->_getPdo();
|
||
|
$this->_setErrorMode();
|
||
|
|
||
|
try {
|
||
|
$pdo->beginTransaction();
|
||
|
|
||
|
// fetch the pgt for the specified pgt_iou
|
||
|
$query = $pdo->prepare($this->retrievePgtSql());
|
||
|
$query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
|
||
|
$query->execute();
|
||
|
$pgt = $query->fetchColumn(0);
|
||
|
$query->closeCursor();
|
||
|
|
||
|
// delete the specified pgt_iou from the database
|
||
|
$query = $pdo->prepare($this->deletePgtSql());
|
||
|
$query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
|
||
|
$query->execute();
|
||
|
$query->closeCursor();
|
||
|
|
||
|
$pdo->commit();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
// attempt rolling back the transaction before throwing a phpCAS error
|
||
|
try {
|
||
|
$pdo->rollBack();
|
||
|
}
|
||
|
catch(PDOException $e) {
|
||
|
}
|
||
|
phpCAS::trace('error reading PGT from database: ' . $e->getMessage());
|
||
|
}
|
||
|
|
||
|
// reset the PDO object
|
||
|
$this->_resetErrorMode();
|
||
|
|
||
|
phpCAS::traceEnd();
|
||
|
return $pgt;
|
||
|
}
|
||
|
|
||
|
/** @} */
|
||
|
|
||
|
}
|
||
|
|
||
|
?>
|