Reputation: 1156
I'm trying to obfuscate the URLs to the pages where content is displayed. Content pages are displayed by getting the content id number as a GET variable in the URL. I want to obfuscate the URL (as is described by this SO post). I tried the methods in both answers but one method gave overly long codes, and the other gave overly predictable codes.
I'm working in PHP, and I'm using a MySQL table to store content; the content id is an automatically incrementing column. This means that if I didn't obfuscate my URLs users would be able to see in the URL exactly how many posts there are on the website, and could change the URL to see different posts. I want to avoid this.
I was hoping to have obfuscation similar to Imgur.com: their content ID codes are each a 5-character code containing letters, capital letters and lowercase letters.
Upvotes: 1
Views: 886
Reputation: 1156
What I've ended up doing is quite simple: I cipher the number (ensuring that the output of the cipher is within a certain range) then I convert the number to base 62.
I chose base 62 because the characters in base 62 are numerics, capital alphabets, and lowercase alphabets. I ensured the output of the cipher was within a certain range so that when converted to base 62 it would have a certain number of digits (in my case I chose six digits in base 62).
To reverse the code, I convert it back to base 10 and reverse the cipher.
Upvotes: 0
Reputation: 668
For a super simple solution that does not really prevent people from reverse engineering your URLs but will deter 99.9999% of users you can do something like
<?php
function hash_id($id){
$crypt = crypt($id, 'Whatever you want to say here. Just SALT it!');
$md5 = md5($crypt . 'You can do another SALT here.');
return substr($md5, 0, 5);
}
if(empty($_GET['page']))
die('missing ?page');
$page = explode('-', $_GET['page']);
if(count($page) != 2)
die('invalid ?page');
list($page_id, $page_key) = $page;
if(!is_numeric($page_id))
die('invalid page id');
$Page = your_function_to_get_page_by_id($page_id);
if(!$Page || hash_id($page_id) != $page_key){
header('Location: /invalid_page.html');
exit;
}
//the URL would look like ?page=55-so3ph
Between crypt and md5 with salts, it would take somebody with a super computer a good chunk of time to start finding the collisions.
Upvotes: 0
Reputation: 668
To avoid needing to do a bunch of "encrypting" and "decrypting" you can use a unique key-pair for each page. Add another field (VARCHAR 5) to your pages table called key and then randomly generate a key for each page.
To generate the key you could crypt a random number
function random_key(){
$crypt = crypt(rand(0,9999999), 'Whatever you want to say here.');
return substr($crypt, 0, 5);
}
Which would result in a URL like ?page=55-so3ph
(?page={$id}-{$key}
)
And then to use it you can do something like
<?php
if(empty($_GET['page']))
die('missing ?page');
$page = explode('-', $_GET['page']);
if(count($page) != 2)
die('invalid ?page');
list($page_id, $page_key) = $page;
if(!is_numeric($page_id))
die('invalid page id');
$Post = your_query_method('SELECT * FROM pages WHERE id = ' . $page_id . ' AND key = "' . your_escape_function($page_key) . '"');
if(!$Post){
header('Location: /invalid_page.html');
exit;
}
//At this point we know that they ID key pair is correct
Upvotes: 1