Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Introduction</strong></p> <p>You can use 2 simple method </p> <ul> <li>Authentication Token </li> <li>Signed Request </li> </ul> <p>You can also combine both of them by using Token for authentication and using signature to verify integrity of the message sent</p> <p><strong>Authentication Token</strong> </p> <p>If you are going to consider matching any identification in the database perhaps you can consider creating authentication token rather than user ID, session, cookies, ip, time stamp, etc! as suggested.</p> <p>Create a random token and save to Database</p> <pre><code>$token = bin2hex(mcrypt_create_iv(64, MCRYPT_DEV_URANDOM)); </code></pre> <ul> <li>This can be easily generated</li> <li>You can guaranteed it more difficult to guess unlike password </li> <li>It can easily be deleted if compromised and re generate another key </li> </ul> <p><strong>Signed Request</strong> </p> <p>The concept is simple, For each file uploaded must meat a specific signature crated using a random generated key just like the token for each specific user </p> <p>This can easily be implemented with HMAC with <code>hash_hmac_file</code> function </p> <p><strong>Combine Both Authentication &amp; Signed Request</strong> </p> <p>Here is a simple Prof of concept </p> <p><strong>Server 1</strong> </p> <pre><code>/** * This should be stored securly * Only known to User * Unique to each User * Eg : mcrypt_create_iv(32, MCRYPT_DEV_URANDOM); */ $key = "d767d183315656d90cce5c8a316c596c971246fbc48d70f06f94177f6b5d7174"; $token = "3380cb5229d4737ebe8e92c1c2a90542e46ce288901da80fe8d8c456bace2a9e"; $url = "http://server 2/run.php"; // Start File Upload Manager $request = new FileManager($key, $token); // Send Multiple Files $responce = $request-&gt;send($url, [ "file1" =&gt; __DIR__ . "/a.png", "file2" =&gt; __DIR__ . "/b.css" ]); // Decode Responce $json = json_decode($responce-&gt;data, true); // Output Information foreach($json as $file) { printf("%s - %s \n", $file['name'], $file['msg']); } </code></pre> <p><em>Output</em> </p> <pre><code>temp\14-a.png - OK temp\14-b.css - OK </code></pre> <p><strong>Server 2</strong></p> <pre><code>// Where to store the files $tmpDir = __DIR__ . "/temp"; try { $file = new FileManager($key, $token); echo json_encode($file-&gt;recive($tmpDir), 128); } catch (Exception $e) { echo json_encode([ [ "name" =&gt; "Execption", "msg" =&gt; $e-&gt;getMessage(), "status" =&gt; 0 ] ], 128); } </code></pre> <p><em>Class Used</em> </p> <pre><code>class FileManager { private $key; function __construct($key, $token) { $this-&gt;key = $key; $this-&gt;token = $token; } function send($url, $files) { $post = []; // Convert to array fromat $files = is_array($files) ? $files : [ $files ]; // Build Post Request foreach($files as $name =&gt; $file) { $file = realpath($file); if (! (is_file($file) || is_readable($file))) { throw new InvalidArgumentException("Invalid File"); } // Add File $post[$name] = "@" . $file; // Sign File $post[$name . "-sign"] = $this-&gt;sign($file); } // Start Curl ; $ch = curl_init($url); $options = [ CURLOPT_HTTPHEADER =&gt; [ "X-TOKEN:" . $this-&gt;token ], CURLOPT_RETURNTRANSFER =&gt; 1, CURLOPT_POST =&gt; count($post), CURLOPT_POSTFIELDS =&gt; $post ]; curl_setopt_array($ch, $options); // Get Responce $responce = [ "data" =&gt; curl_exec($ch), "error" =&gt; curl_error($ch), "error" =&gt; curl_errno($ch), "info" =&gt; curl_getinfo($ch) ]; curl_close($ch); return (object) $responce; } function recive($dir) { if (! isset($_SERVER['HTTP_X_TOKEN'])) { throw new ErrorException("Missing Security Token"); } if ($_SERVER['HTTP_X_TOKEN'] !== $this-&gt;token) { throw new ErrorException("Invalid Security Token"); } if (! isset($_FILES)) { throw new ErrorException("File was not uploaded"); } $responce = []; foreach($_FILES as $name =&gt; $file) { $responce[$name]['status'] = 0; // check if file is uploaded if ($file['error'] == UPLOAD_ERR_OK) { // Check for signatire if (isset($_POST[$name . '-sign']) &amp;&amp; $_POST[$name . '-sign'] === $this-&gt;sign($file['tmp_name'])) { $path = $dir . DIRECTORY_SEPARATOR . $file['name']; $x = 0; while(file_exists($path)) { $x ++; $path = $dir . DIRECTORY_SEPARATOR . $x . "-" . $file['name']; } // Move File to temp folder move_uploaded_file($file['tmp_name'], $path); $responce[$name]['name'] = $path; $responce[$name]['sign'] = $_POST[$name . '-sign']; $responce[$name]['status'] = 1; $responce[$name]['msg'] = "OK"; } else { $responce[$name]['msg'] = sprintf("Invalid File Signature"); } } else { $responce[$name]['msg'] = sprintf("Upload Error : %s" . $file['error']); } } return $responce; } private function sign($file) { return hash_hmac_file("sha256", $file, $this-&gt;key); } } </code></pre> <p><strong>Other things to consider</strong> </p> <p>For better security you can consider the follow </p> <ul> <li>IP Lock down </li> <li>File Size Limit </li> <li>File Type Validation </li> <li>Public-Key Cryptography </li> <li>Changing Date Based token generation</li> </ul> <p><strong>Conclusion</strong> </p> <p>The sample class can be extended in so many ways and rather than use URL you can consider a proper <code>json RCP</code> solution</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload