[PHP, OOP] Zugriffsschutz für Objekt auf eigene Eigenschaft

joschilein

Multitalent
ID: 9301
L
5 Mai 2006
1.393
151
(Das ganze Problem ist wie immer auf einfache und anschauliche Beispiele abstrahiert, damit unnötige Vielfalt nicht zu sehr vom Thema abweicht)

Es gibt zwei Klassen (Kontoinhaber und Konto). Da mit der Klasse Konto aber auch Buchungen vorgenommen werden können/müssen, könnte jedes Klasse Kontoinhaber selbständig Buchungen vornehmen, was nicht erwünscht ist. Aus diesem Grund wurden Objekte beider Klassen im ersten Ansatz nebeneinander gespeichert, ungefähr so:
PHP:
$sammelbox = array(array('konto' => $konto1_obj, 'inhaber' => $kontoinhaber1_obj), array('konto' => $konto2_obj, 'inhaber' => $kontoinhaber2_obj));


Im zweiten Ansatz überlege ich mir nun, ob man nicht das Konto-Objekt doch an das Kontoinhaber-Objekt übergeben könnte, ohne dass dieses auf auf die Methode buchung() zugreifen kann, andere Methoden wie kontostand() aber problemloser und schneller als in der ersten Version erreichen kann.

Dabei habe ich nun folgende Version erstellt:
PHP:
class Konto{
	private $_kontostand = 0;
	private $_key        = NULL;

	function set_key($key){
		if ($this->_key === NULL) {
			$this->_key = md5($key);
		} else {
			return FALSE;
		}
	}

	function valid_key($key){
		if ($this->_key === md5($key)) {
			return TRUE;
		} else {
			return FALSE;
		}
	}

	function __construct($anfangsbestand){
		$this->_kontostand = $anfangsbestand;
	}

	function buchung($key = NULL, $anzahl = NULL){
		if ($this->valid_key($key) === TRUE AND is_numeric($anzahl)) {
			$this->_kontostand+= $anzahl;
			return TRUE;
		} else {
			return FALSE;
		}
	}

	function kontostand(){
		return $this->_kontostand;
	}
}



class Kontoinhaber_Standard {
	private   $_konto_obj   = NULL;
	protected $_inhabername = '';

	final function __construct($name){
		$this->_inhabername = $name;
	}

	final function set_konto_obj($konto_obj){
		$this->_konto_obj = $konto_obj;
	}

	final function konto(){
		return $this->_konto_obj;
	}
}

class Kontoinhaber_Typ1 extends Kontoinhaber_Standard {
	function wieistdeinkontostand(){
		return $this->konto()->kontostand();
	}

	function machewasdusollst($a){
		$this->_manipulationsversuch1();
		$this->_manipulationsversuch2();
		return $a*2;
	}

	private function _manipulationsversuch1(){
		$this->konto()->buchung('XYZ', 1000000);
	}

	private function _manipulationsversuch2(){
		$str = print_r($this->konto(), TRUE);
		//..
	}
}


// Beispielhafte Verwendung
$key = 'ABC';

$konto_obj = new Konto(1000);
$konto_obj->set_key($key);

$kontoinhaber = new Kontoinhaber_Typ1('Böser Kontoinhaber');
$kontoinhaber->set_konto_obj($konto_obj);

echo 'Bankauskunft: '.$kontoinhaber->konto()->kontostand().'<br />';
echo 'Inhaberauskunft: '.$kontoinhaber->wieistdeinkontostand().'<br />';
$kontoinhaber->konto()->buchung($key, 100);
echo 'Bankauskunft: '.$kontoinhaber->konto()->kontostand().'<br />';
echo 'Inhaberauskunft: '.$kontoinhaber->wieistdeinkontostand().'<br />';
$kontoinhaber->machewasdusollst(5);
echo 'Bankauskunft: '.$kontoinhaber->konto()->kontostand().'<br />';
echo 'Inhaberauskunft: '.$kontoinhaber->wieistdeinkontostand().'<br />';

Man sieht also, dass es $kontoinhaber schwer gemacht wird bei einer angestoßenen erwünschten Aktion nebenbei noch ungewollte Dinge zu tun, da 1. ohne Schlüssel ein Zugriff auf buchung() kein sinnvolles Ergebnis bringt und 2. eine Analyse der Konto-Objektes maximal den Hash des Schlüssels liefert.
Zudem wird durch die Vererbung von Kontoinhaber_Standard und der dort als final deklarierten Methoden eine Überschreibung und damit die heimliche Erzeugung eines weiteren (frei manipulierbaren) Konto-Objektes unterbunden.

Ist dieses Vorgehen ausreichend? Vielleicht sollte noch geprüft werden, ob diese Vererbung auch tatsächlich stattgefunden hat.

Warum eigentlich? Das ganze soll sowas ähnliches sein wie Robotwars für Java. Zwar ohne entsprechende Grafik und auch keinen Roboterkrieg, aber eben ein aufeinandertreffen verschiedener Stategien, zu der jeder was beitragen kann und eben einen eigenen Kontoinhaber programmieren kann. Dementsprechend sollte ein kurzer Blick über die erstellten Klassen genügen, um derlei Manipulationsversuche schnell abschätzen zu können bzw. soweit möglich überhaupt nicht erst anwendbar zu machen.