开发者

How to obscure a GET variable?

I'm toying with the idea of creating automatic electronic certificates. It's pretty easy to create custom certificates using the fpdf PHP class. The way I have it set up is that given a URL

http://www.example.com/makepdf.php?name=myname&class=classname

you get a PDF certificate with the student name and the class they took taken from the $_GET variable. Of course, this means that anyone could manipulate the URL to very easily create a custom certificate. (They could do this in Photoshop anyway, but the idea is to make manipulating the certificate not totally trivial.) Once a class is over, I want to send a mail merge to everyone with a unique URL for their certificate.

How would you approach this problem? Shou开发者_如何学运维ld I just create a set of random numbers and associate these with the student/workshop pairs in a database? Are there standard ways of approaching this problem?


Couple solutions stand out:

  • Store the names & classes in a database, and reference them with a numeric ID instead of passing the data in the request
  • Keep the information in the request, but add a secure hash that will prevent tampering with the data

The hash mechanism would be something like this:

When generating the link for the certificate, you have $name and $class. You'll create a third GET variable that is a hash of $name, $class, and a secret string that only your program knows. Something like this:

$salt = "this is my secret";
$hash = md5($name . $class . $salt);
$url = "http://www.mysite.com/certificate.php?name=" . urlencode($name) . "&class=" . urlencode($class) . "&hash=" . $hash;

Now when a user hits your certificate generation page, you must verify the hash:

$salt = "this is my secret";
$expected = md5($_GET['name'] . $_GET['class'] . $salt);
if ($expected != $_GET['hash']) {
  die("You are not authorized");
} else {
  // User is OK; generate the certificate
}


Yes, if you want to limit your inputs to a fixed pool, then creating a database full of random keys is the way I would go.

If you want a quicker and dirtier way to do it, just generate the keys into a text file, use a script to pull the file apart to send them to the recipients, and have your PHP certificate generator read from a copy of the file on the server.


Assuming you are generating these URLs yourself on the server, you could join all your parameter values together into a string:

hash_string = "myname:classname";

Then append a final parameter that's a hash of that string along with some secret seed:

query_string .= "&h=" . md5("my_secret_key:" . hash_string)

Then, when you get the query back, just check to make sure that the hash matches:

hash_string = params['name'] . ':' . params['class'];
if (params['h'] == md5("my_secret_key:" . hash_string)) ...

I don't really know PHP syntax, but you get the idea.


Your best bet would be to have a list of students/classes (some kind of database) and only allow generation of allowed certificates. That way you don't need to obfuscate the name of the student or class, because only valid certificates can be generated.

If that's too much to ask - you could generate a MD5 hash based on the combination and some salt, then add that hash to the URL. That way the salt would need to be know to forge a URL.

http://www.example.com/makepdf.php?name=Tim&class=PHP&hash=c2c455ce438112b44499561131321126

Then the generation script just does this:

$hash = md5($_GET['name'] . $_GET['class'] . $salt);
if($hash != $_GET['hash']){
  //invalid request
}

Of course you'll need to generate the URL's with the same salt.


Should I just create a set of random numbers and associate these with the student/workshop pairs in a database?

Yes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜