Asked  7 Months ago    Answers:  5   Viewed   32 times

What would be useful solutions for hiding true database object ID in URL for security purposes? I found that one of the solutions would be:

1) Using hashids open source project

2) Using something like same old md5 on creation of the object to generate hash and store it in database, then use it in url's and querying by them, but the drawback is that querying by auto-incremented primary keys (IDs) is faster than hashes. So I believe the possibility to hash/unhash would be better?

Also as I'm on Symfony, are there maybe bundles that I could not find or built in functionalities that would help?

Please tell me what you found useful based on your experiences.



This question has been asked a lot, with different word choice (which makes it difficult to say, "Just search for it!"). This fact prompted a blog post titled, The Comprehensive Guide to URL Parameter Encryption in PHP .

What People Want To Do Here

Some encryption function is used to deterministically retrieve the ID

What People Should Do Instead

Use a separate column


Typically, people want short random-looking URLs. This doesn't allow you much room to encrypt then authenticate the database record ID you wish to obfuscate. Doing so would require a minimum URL length of 32 bytes (for HMAC-SHA256), which is 44 characters when encoded in base64.

A simpler strategy is to generate a random string (see random_compat for a PHP5 implementation of random_bytes() and random_int() for generating these strings) and reference that column instead.

Also, hashids are broken by simple cryptanalysis. Their conclusion states:

The attack I have described is significantly better than a brute force attack, so from a cryptographic stand point the algorithm is considered to be broken, it is quite easy to recover the salt; making it possible for an attacker to run the encoding in either direction and invalidates property 2 for an ideal hash function.

Don't rely on it.

Wednesday, March 31, 2021
answered 7 Months ago

I think you are quite on the right way.

One thing I would not do like you said, though, is about this part :

then use apache mod_rewrite and create shorten url and then redirect.

I don't think I'd create an Apache RewriteRule, nor use mod_rewrite.

When receiving an short url, like, Id would :

  • decrypt the "MYID" part to the id number in DB
  • fetch the URL from database
  • just redirect to that URL from some server code (like PHP, using the header function)

A bit like this I guess :

// fetch $urlFull from DB (corresponding to the MYID received in GET)
header('HTTP/1.x 301 Moved Permanently');
header('Location: ' . $urlFull);

(edit) If by mod_rewrite you meant "transform to", oh, yes, in this case, of course !

I'm using something like this on one of my sites, btw :

RewriteEngine on
RewriteCond %{REQUEST_URI}  !^/index.php
RewriteRule ^(.*)$ /index.php?hash=$1   [L]

Hope this helps :-)

Wednesday, March 31, 2021
answered 7 Months ago

So something like this:

RewriteRule ^article/([0-9a-zA-Z_-]+)$ article.php?title=$1 [NC,L]
Saturday, May 29, 2021
answered 5 Months ago

Search comment //ADD THIS LINE TO YOUR CODE in following modified method of yours.

- (void) gettingData:(NSString *)dbPath {
    NSLog(@"Data base path is %@",dbPath);
    if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
        const char *sql = "select * from Product";
        sqlite3_stmt *selectstmt;
        if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK)
            while(sqlite3_step(selectstmt) == SQLITE_ROW)
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char*)sqlite3_column_text(selectstmt, 0)] forKey:@"ProductName"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)] forKey:@"ProductBarcode"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)] forKey:@"ProductImage"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 3)] forKey:@"ProductIngredients"];
                [membersInfoDict setValue:[NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 4)] forKey:@"ProductStatus"];

                    [membersInfoArray addObject:membersInfoDict];
                    membersInfoDict = nil;
                    //  NSLog(@"Entered and return");
        sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
Wednesday, July 28, 2021
answered 3 Months ago

This is most likely caused by saving asynchronously instead of synchronously:

Be careful when saving entities with an autogenerated Long @Id field. A synchronous save() will populate the generated id value on the entity instance. An asynchronous save() will not; the operation will be pending until the async operation is completed.


It should fix the problem to change the save() method

From this:

private void save(DownloadTask downloadTask) {
    Closeable closeable = begin();

To this:

private void save(DownloadTask downloadTask) {
    Closeable closeable = begin();
    ofy().save().entity(downloadTask).now();  // Added .now()

This fixed the problem for me in a similar situation where I was testing with Junit on a data model involving a linked object model.

Saturday, August 21, 2021
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :