简体   繁体   中英

How to do Imgur-style obfuscation of content id number in website URL? (PHP&MySQL)

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.

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM