Skip to content

Instantly share code, notes, and snippets.

@jaspertandy
Created January 6, 2012 14:20
Show Gist options
  • Save jaspertandy/1570808 to your computer and use it in GitHub Desktop.
Save jaspertandy/1570808 to your computer and use it in GitHub Desktop.
<?php
/**
* Simple XSRF protection.
*/
class Session_Key {
/**
* constants, USER and FORM are used to identify session data, USER, FORM and FORMID are used as
* input names so validation is encapsulated easily
*/
const USER = 'SESSIONKEY_USERKEY';
const FORM = 'SESSIONKEY_FORMKEY';
const FORMID = 'SESSIONKEY_FORMID';
/**
* easier access to stuff stored in session. Can't be bothered writing $_SESSION all the time
*/
protected $user;
protected $form;
/**
* the currently-generated form key and id. Really, this class should be called every time
* you want a new one, but reloads are handled as best as possible internally
*/
protected $current_form_key = '';
protected $current_form_id = '';
public function __construct(){
if ( !array_key_exists( self::USER , $_SESSION ) ) {
$this->user_key();
$_SESSION[ self::FORM ] = array();
}
$this->reload();
}
/**
* As we only ever modify the data in the session to ensure persistence, this function is
* needed to make sure that the class internals are always up-to-date
*
* call every time a modification is made to the session data
*/
protected function reload(){
$this->user = $_SESSION[ self::USER ];
$this->form = $_SESSION[ self::FORM ];
}
/**
* Generate a new form key and id
*/
protected function restart(){
$this->current_form_key = $this->generate_key();
$this->current_form_id = $this->generate_key();
}
/**
* generate a random string to use as a key
*/
protected function generate_key(){
return sha1( microtime(true) . mt_rand() . uniqid() );
}
/**
* generate a new user key. One one-time per session is needed really
*/
public function user_key(){
$_SESSION[ self::USER ] = $this->generate_key();
}
/**
* create a new form key
*/
public function form_key(){
$this->restart();
$_SESSION[ self::FORM ][ $this->current_form_id ] = $this->current_form_key;
$this->reload();
return $key;
}
/**
* return the HTML needed to validate with data generated by this class
*/
public function form_fields(){
$this->form_key();
return '<input type="hidden" name="'.self::USER.'" value="'. $this->user .'"/><input type="hidden" name="'.self::FORM.'" value="'. $this->current_form_key .'"/><input type="hidden" name="'.self::FORMID.'" value="'. $this->current_form_id .'"/>';
}
/**
* make sure that the form sent was sent by this class
*/
public function validate( Validation $obj , $field ){
$this->reload();
if ( $obj->{ self::USER } !== $this->user ) return false; // User session key mismatch
if ( $obj->{ self::FORM } !== $this->form[ $obj->{ self::FORMID } ] ) return false; // Form key mismatch
unset( $_SESSION[ self::FORM ][ $obj->{ self::FORMID } ] );
$this->reload();
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment