php token match does not work - php

i am doing form validator(using tokens).
Page is based on smarty. So in class Articles i have the followin function:
public static function getToken(){
self::$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = self::$token;
}
Then in .tpl file i have inserted the value like this:
<input type="hidden" name="token" value="{Articles::$token}">
After the form is submitted the check is run in index.php:
if(isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
Articles::addComment($item, $_POST['name'], $_POST['email'], $_POST['comment']);
}
The issue is that I get different tokens. For example, I echoed the $_SESSION['token'] and compared in with the value in the form (view source).
Also after submit i tried to echo both values ($_SESSION ['token'] and $_POST ['token]) they are different as well. Obviously, the form is not submitting.

CSRF tokens need not be mapped 1:1 for users. What if you have more than one form on a page? What if a user has more than one browser window open?
Define something to store 0..n tokens, set a reasonably short validity period on them, and [optionally] define what they are valid for. Eg:
class Token {
protected $id, $expiry;
public function __construct($expiry=300, $id=NULL) {
$this->expiry = time() + $expiry;
if( is_null($id) ) {
// actual secure ID generation.
$this->id = bin2hex(random_bytes(32));
} else {
$this->id = $id;
}
}
public function getID() {
return $id;
}
public function isValid() {
return time() < $expiry;
}
}
class YourApp {
public function newToken() {
$token = new Token();
$_SESSION['tokens'][$token->getID()] = $token;
return $token
}
public function checkToken($token_id) {
if( key_exists($token_id, $_SESSION['tokens']) ) {
$cur = $_SESSION['tokens'][$token_id];
unset($_SESSION['tokens'][$token_id]; // single use only!
return $cur->isValid();
} else {
return false;
}
}
public function flushOldTokens() {
$_SESSION['tokens'] = array_filter(
$_SESSION['tokens'],
function($t){return $t->isValid();}
);
}
}

Related

How to get submitted variable into a function

I am very sorry if this is very obvious, but I am banging my head against the wall on how to solve this
I have a form and I would like to use the submitted form value in to a function
the form:
form.php
<form action="my.php" method="post" enctype="multipart/form-data">
<input id="my-item-calc" name="my-item-calc" value="29.00">
<td>
<input type="submit">
</form>
my.php
class Jcart{
private $calcdel =0;
public function get_contents() {
return $items;
return $calc['calcdel'];
}
private function add_calc($calcdel){
$validCalcdel = false;
//Verify if the calculate value is numberic
if (is_numeric($calcdel)) {
$validCalcdel = true;
}
if ($validCaldel !== false) {
$this->calcdel = $calcdel;
}
}
public function display_cart() {
$config = $this->config;
$errorMessage = null;
// Simplify some config variables
$checkout = $config['checkoutPath'];
$priceFormat = $config['priceFormat'];
$calcdel = $config['calc']['calcdel'];
// Use config values as literal indices for incoming POST values
// Values are the HTML name attributes set in config.json
$calcdel= $_POST[$calcdel];
if ( isset($_POST[$calcdel]) ) {
$calcdel = $_POST[$calcdel];
$calcAdded = $this->add_calc($calcdel);
if ($calcAdded = true){
$this->calcdel = $calcdel;
}
}
}
}
When I submit the form it will echo 29.00 for the $calcdel how ever this $this->calcdel output is empty
Any help how I would be able to pass the value into $this->calcdel and echo it out
Hope this will work
class Jcart{
private $calcdel =0;
public function get_contents() {
return $items;
return $calc['calcdel'];
}
private function add_calc($calcdel){
$validCalcdel = false;
//Verify if the calculate value is numberic
if (is_numeric($calcdel)){
$validCalcdel = true;}
if ($validCaldel !== false){
$this->calcdel = $calcdel;
}
}
public function display_cart() {
$config = $this->config;
$errorMessage = null;
// Simplify some config variables
$checkout = $config['checkoutPath'];
$priceFormat = $config['priceFormat'];
$calcdel = $config['calc']['calcdel'];
// Use config values as literal indices for incoming POST values
// Values are the HTML name attributes set in config.json
$calcdel= $_POST[$calcdel];
$calcAdded = $this->add_calc($calcdel);
if ($calcAdded){
$this->calcdel = $calcdel;
}
}}
$jcart = new Jcart();
if (isset($_POST[$calcdel]))
{
$jcart->display_cart();
}

Load a PHP class multiple times

I've created a class which has multiple private an public functions and an construct function. It's an client to connect to the vCloud API. I want two objects loaded with different initiations of this class. They have to exist in parallel.
$vcloud1 = new vCloud(0, 'system');
$vcloud2 = new vCloud(211, 'org');
When I check the output of $vcloud1 it's loaded with info of $vcloud2. Is this correct, should this happen? Any idea how I can load a class multiple times and isolate both class loads?
This is part of my class, it holds the most important functions. Construct with user and org to login to. If info in the DB exists, then we authenticate with DB info, else we authenticate with system level credentials. So I would like to have two class loads, one with the user level login and one with system level login.
class vCloud {
private $client;
private $session_id;
private $sdk_ver = '7.0';
private $system_user = 'xxxxxxxxxxx';
private $system_password = 'xxxxxxxxxxxxxxxxx';
private $system_host = 'xxxxxxxxxxxxx';
private $org_user;
private $org_password;
private $org_host;
private $base_url;
public function __construct($customerId, $orgName) {
if ($this->vcloud_get_db_info($customerId)) {
$this->base_url = 'https://' . $this->org_host . '/api/';
$this->base_user = $this->org_user . "#" . $orgName;
$this->base_password = $this->org_password;
} else {
$this->base_url = 'https://' . $this->system_host . '/api/';
$this->base_user = $this->system_user;
$this->base_password = $this->system_password;
}
$response = \Httpful\Request::post($this->base_url . 'sessions')
->addHeaders([
'Accept' => 'application/*+xml;version=' . $this->sdk_ver
])
->authenticateWith($this->base_user, $this->base_password)
->send();
$this->client = Httpful\Request::init()
->addHeaders([
'Accept' => 'application/*+xml;version=' . $this->sdk_ver,
'x-vcloud-authorization' => $response->headers['x-vcloud-authorization']
]);
Httpful\Request::ini($this->client);
}
public function __destruct() {
$deleted = $this->vcloud_delete_session();
if (!$deleted) {
echo "vCloud API session could not be deleted. Contact administrator if you see this message.";
}
}
private function vcloud_delete_session() {
if (isset($this->client)) {
$response = $this->client::delete($this->base_url . 'session')->send();
return $response->code == 204;
} else {
return FALSE;
}
}
public function vcloud_get_db_info($customerId) {
global $db_handle;
$result = $db_handle->runQuery("SELECT * from vdc WHERE customer=" . $customerId);
if ($result) {
foreach ($result as $row) {
if ($row['org_host'] != "") {
$this->org_user = $row['org_user'];
$this->org_password = $row['org_password'];
$this->org_host = $row['org_host'];
return true;
} else {
return false;
}
}
} else {
return false;
}
}
public function vcloud_get_admin_orgs() {
$response = $this->client::get($this->base_url . 'query?type=organization&sortAsc=name&pageSize=100')->send();
return $response->body;
}
}
$vcloud1 = new vCloud('user1', 'system');
$vcloud2 = new vCloud('user2', 'org');
This is enough to make two instances which are not related.
I suppose your database is returning the same results.
How about providing a custom equals method to each object that retreives an instance of vCloud?
class vCloud {
//Other definitions
public function equals(vCloud $other){
//Return true if $other is same as this class (has same client_id etc etc)
}
}
So you just need to do as the code says:
$vcloud1 = new vCloud('user1', 'system');
$vcloud2 = new vCloud('user2', 'org');
if($vcloud1.equals($vclous2)){
echo "Entries are the same";
} else {
echo "Entries are NOT the same";
}
Also you may need to have various getter and setter methods into your class definitions. What is needed for you to do is to fill the equals method.

Variable to another php file

I have a php file(register.php) with a public function register($data) where errors are validated.Then errors are counted and if no errors are found, validation is passed.
register.php:
class ARegister {
public function register($data) {
$user = $data['userData'];
//validate provided data
$errors = $this->validateUser($data);
if(count($errors) == 0) {
//first validation
}
}
public function validateUser($data, $botProtection = true) {
$id = $data['fieldId'];
$user = $data['userData'];
$errors = array();
$validator = new AValidator();
if( $validator->isEmpty($user['password']) )
$errors[] = array(
"id" => $id['password'],
"msg" => Lang::get('password_required')
);
return $errors;
}
The problem is, that I need to get this confirmation of validated data to my other php file (othervalidation.php) where I've made another validation:
othervalidation.php:
<?php
require 'register.php';
if ( !empty($action) ) {
switch ( $action ) {
case 'process_payment':
try {
$instance = new ARegister();
if($instance->validateUser($data, $errors)) {
throw new Exception('Validation error');
}
} catch (Exception $e) {
$status = false;
$message = $e->getMessage();
}
}
How can I send the result of $errors variable to my other validation (othervalidation.php)?
I looked at your new code design and here's the new problems I found.
First, in your register function, you use the errors variable as an integer while your validate function returns an array. You got two possibilities here.
You can change your register method to check out if your error array is empty like this:
if(empty($errors)) {
//first validation
}
Count is also valid, but I still prefer empty since it's syntactically clearer. Furthermore, the count function returns 1 if the parameter is not an array or a countable object or 0 if the parameter is NULL. As I said, it is a functional solution in your current case but, in some other contexts, it might cause you unexpected results.
Here in your method declaration, I see that you are expecting a boolean (botProtection).
public function validateUser($data, $botProtection = true) {
But you are supplying an errors parameter
if($instance->validateUser($data, $errors)) {
You don't provide me the declaration of the errors variable, but it is probably not matching the bot protection parameter your function is expecting. PHP is using lose typing, it is useful but, once again, you got to be careful for bugs hard to find. For public function, you should always make sure a way or another that the supplied parameter won't lead to code crash.
In your code, the data parameter seems to be an array. You can use parameter hinting to force the use of array like this:
public function register(array $data) {
public function validateUser(array $data, $botProtection = true) {
And even specific class (as if you where using "instance of" in a condition)
public function register(MyDataClass $data) {
public function validateUser(MyDataClass $data, $botProtection = true) {
Also, you're not even using the botProtection parameter in your validateUser method.
On the same function call:
if($instance->validateUser($data, $errors)) {
you are expecting a Boolean (true or false), but the method returns an array. If you want to use the code the way it is currently designed, you must use it like this
if(!empty($instance->validateUser($data, $errors)) {
Here, I'm not so sure it is necessary to use exception. Ain't it be easier to design your code like this?
if(!empty($instance->validateUser($data, $errors)) {
$message = 'Validation error';
}
In your validate function, is the "isEmpty" function also validating if the client provided a password?
If that's the case you could validate it like this:
if(!in_array($user['password']) or empty($user['password']))
With those corrections, your code should be functional.
Here's a sample of how I would had design your code (considering the code sample provided):
class ARegister {
public function register($data) {
$user = $data['userData']; //don't declare it here, all the user validations must be done in validateUser($data, &$errors)
$errors = array();
if($this->validateUser($data, $errors)) {
//first validation
}
}
/**
* Note: If you are not returing more than one error at the time, $errors should be a string instead of an array.
*/
public function validateUser($data, array &$errors) {
$isValid = false;
if (in_array($data['fieldId']) and in_array($data['fieldId']['password']) and in_array($data['userData'])){
if(!in_array($data['userData']['password']) or empty($data['userData']['password'])){
$errors[$data['fieldId']['password']] = Lang::get('password_required');
}
else{
$isValid = true;
}
}
else{
//an invalid data array had been provided
}
return $isValid;
}
For the next part, if the code is executed directly in the view and you are a beginner, create a procedural external controller file (all functions will be public...). If you are a professional, you MUST create a class to encapsulate the treatment.
You must not do treatment directly in the view. The view is a dumb placeholder for data presentation and collecting client's input. The sole action it must do is display the data sent by the controller and send back the client's input to the controller.
The treatment on data is the controller responsibility.
if (!empty($action) ) {
$errors =array();
switch ( $action ) {
case 'process_payment':
$instance = new ARegister();
if($instance->validateUser($data, $errors)) {
//the user is valid, do the treatment
}
else
PageManager::dispayError($errors);
}
unset($instance);
}
}
Here's an example how you can centralize your error display
/**
* Can be more complexe than that, but I'm at my father's home at four hundred kms away from Montreal right now..
*/
public static function dispayError($errors, $size = 4){
if (is_numeric($size)){
if ($size < 0){
$size = 1;
}
elseif($size > 5){
$size = 5;
}
}
else{
$size = 4;
}
if (is_scalar($errors)){
echo '<h' . $size . 'class="ERROR_MESSAGE">' . $errors . '</h' . $size . '><br>';
}
elseif (is_array($errors)){
foreach ($errors as $error){
if (is_scalar($error)){
echo '<h' . $size . 'class="ERROR_MESSAGE">' . $error . '</h' . $size . '><br>';
}
}
}
}
Of course, you can also support many kind of message:
public static function dispayError($errors, $size = 4){
self::displayMessage("ERROR_MESSAGE", $errors, $size=4);
}
private static displayMessage($class, $messages, $size=4)
Well, took me two hours to write that. I hope you have now enough material to build an efficient, reusable and, no less important, safe code design.
Good success,
Jonathan Parent-Lévesque from Montreal
You can try something like this:
class ARegister {
private $error = 0;
public function register($data) {
if (!$this->validateUser($data)){
$this->error++;
}
}
public function getErrorCount(){
return $this->error;
}
public resetErrorCount(){
$this->error = 0;
}
Or pass the error by reference:
public function register(&$error, $data) {
if (!$this->validateUser($data)){
$error++;
}
}
Personally, I would do all the validation in the same method (in the class for encapsulation), use an error message parameter (passed by reference) to return why the validation failed and use the return statement to return true or false.
class MyClass{
public function validation(&$errorMessage, $firstParameter, $secondParameter){
$success = false;
if (!$this->firstValidation($firstParameter)){
$errorMessage = "this is not working pal.";
}
elseif (!this->secondeValidation($firstParameter)){
$errorMessage = "Still not working buddy...";
}
else{
$success = true;
}
return $success;
}
private function firstValidation($firstParameter){
$success = false;
return $success;
}
private function secondeValidation($secondParameter){
$success = false;
return $success;
}
}
In your other file:
<?php
$instance = new MyClass();
$errorMessage = "";
if ($instance->validation($errorMessage, $firstParameter, $secondParameter)){
echo "Woot, it's working!!!";
}
else{
echo $errorMessage;
}
?>
Is one of these code solutions fit your needs?
Jonathan Parent-Lévesque from Montreal

Auto mapping method parameters to $_POST data (MVC)

Imagine I have a URL that loads a controller if the name matches (Ignoring any security issues with this at the moment hehe)
public function Load( $controller, $action = "Index" )
{
require_once( "Controllers/" . $controller . "Controller.php" );
$controllerName = $controller . "Controller";
$loadedController = new $controllerName();
$actionName = "ActionResult_" . $action;
$loadedController->$actionName();
}
Now imagine I want a log in form to send its $_POST details as parameters of the receiving controller launched above:
<?php
class ExcelUploadController extends Controller
{
public function ActionResult_Login( $username = NULL, $password = NULL )
{
// The parameters need to be mapped to the $_POST parameters names probably from the Load method somewhere and pumped in to the $loadedController->$actionName();
$post_username = $username;
$post_password = $password;
$this->ReturnView( "ExcelUpload/Index" );
}
}
?>
But also so that it does not matter what order the parameters are declared, it matches the parameter in the function based on the $_POST key.
How might I go about doing this, any ideas?
So to clarify if this doesn't make sense.. the method might look something like this:
public function Load( $controller, $action = "Index" )
{
require_once( "Controllers/" . $controller . "Controller.php" );
$controllerName = $controller . "Controller";
$loadedController = new $controllerName();
$actionName = "ActionResult_" . $action;
$checkIfPostData = $_POST;
if( isset( $checkIfPostData ) )
{
// Do some funky wang to map the following $loadedController->$actionName();
// with the username and password or any other $_POST keys so that in the calling method, I can grab hold of the $_POST values
}
$loadedController->$actionName();
}
What your are looking for is call_user_func_array()
EDIT, to reply to comment :
You have two options: rewrite all your function so that they accept only one array() as argument and you parse that array for values. A bit fastidious but it can be useful in some cases. Or you can request for the required argument of a function:
// This will create an object that is the definition of your object
$f = new ReflectionMethod($instance_of_object, $method_name);
$args = array();
// Loop trough params
foreach ($f->getParameters() as $param) {
// Check if parameters is sent through POST and if it is optional or not
if (!isset($_POST[$param->name]) && !$param->isOptional()) {
throw new Exception("You did not provide a value for all parameters");
}
if (isset($_POST[$param->name])) {
$args[] = $_POST[$param->name];
}
if ($param->name == 'args') {
$args[] = $_POST;
}
}
$result = call_user_func_array(array($instance_of_object, $method_name), $args);
That way your array will be properly constructed.
You can also add some specific treatment whether a parameter is optional or not (I guess you can understand how to do it from the code I gave you ;)
Since the data is being sent through POST you don't need to pass any parameters to your method:
class ExcelUploadController extends Controller {
private $userName;
private $login;
public function ActionResult_Login() {
$this->userName = $_POST['username'];
$this->login = $_POST['login'];
}
}
Don't forget to sanitize and validate the user input!

Function to set an auth_token

In my form I have a hidden field:
<input type="hidden" name="auth_token" value="<?php echo $auth_token; ?>">
This value is also stored in a session and a variable:
$_SESSION['auth_token'] = hash('sha256', rand() . time() . $_SERVER['HTTP_USER_AGENT']); # TODO: put this in a function
$auth_token = $_SESSION['auth_token'];
When the form is submitted the two values are compared. It's a basic form token.
Should this be made into two functions or just one when refactored? set_form_token() and get_form_token(), get_form_token() returning the session value, then I can compare it in my main code. What is the proper way of doing this?
EDIT:
Considering both Joel L and RobertPitt's answers I have made these:
function set_auth_token()
{
if (!isset($_SESSION['auth_token']))
{
$_SESSION['auth_token'] = hash('sha256', rand() . time() . $_SERVER['HTTP_USER_AGENT']);
}
}
function get_auth_token()
{
if (isset($_SESSION['auth_token']))
{
return $_SESSION['auth_token'];
}
else
{
die('No auth token.');
}
}
function check_auth_token()
{
if (array_key_exists('auth_token', $_SESSION) && array_key_exists('auth_token', $_POST))
{
if ($_SESSION['auth_token'] === $_POST['auth_token'])
{
# what happens if user fills the form in wrong first time(?)
$_SESSION['auth_token'] = hash('sha256', rand() . time() . $_SERVER['HTTP_USER_AGENT']);
}
else
{
return false;
}
}
else
{
return false;
}
}
I can then check if check_auth_token returns false or not and then record it after the form has been submitted. Would this be acceptable?
In my app, I actually have the following helper functions for using tokens:
generateToken() // generate and return hash, used in login process.
// hash then saved to session
getToken() // returns user's token from session
tokenField() // shortcut for echo '<input type="hidden" ... value="getToken()" />';
// used in page templates
checkToken() // get token from either 1) $_POST 2) request header or 3) $_GET
// and compare with getToken(). generate error if invalid.
The checkToken() function checks 3 locations because the request can be GET or POST, and either of those could be via AJAX. And I have my AJAX helper automatically insert the token in the header for each request).
This way, I only need to call checkToken() everywhere the check is needed, and can therefore change the impelmentation details quite easily.
For instance, I can start using one-time tokens by changing only getToken() and checkToken().
If you manually compare if (get_form_token() == $token) everywhere in your code, you have no such flexibility.
firstly you should understand exactly what the workflow is, and Joel L explains that very simply.
You should encapsulate the methods in a class to keep everything together, some thing like sp:
class FormTokenizer
{
private $context = "";
public function __construct($auth_token = "auth_token")
{
$this->context = $context;
}
public function generateToken()
{
$_SESSION[form_tokens][$this->context] = hash('sha256', rand() . time() . $_SERVER['HTTP_USER_AGENT']);
return $this;
}
public function getToken()
{
return isset($_SESSION[form_tokens][$this->context]) ? $_SESSION[form_tokens][$this->context] : false;
}
function generateField()
{
return sprintf('<input type="hidden" name="a_%s" value="%s">',$this->context,$this->getToken());
}
public function validateToken()
{
if(isset($_POST["a_" . $this->context]))
{
return $this->getToken() == $_POST["a_" . $this->context];
}
return false;
}
}
and a simple usage would be:
$Token = new FormTokenizer("registration");
if(isset($_POST))
{
if($Token->validateToken() === false)
{
//Token Onvalid
}
}
//Generate a fresh token.
$hidden_input = $Token->generateToken()->generateField();

Categories