Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

URL encryption

Dear all,

I want to encrypt the url (except domain name part) in listing page and then decrypt the url so as to execute the request.

for example

suppose my domain is localhost and my controller is suppliers and action/method is editAction and supplier id is 55 then my url is http://localhost/suppliers/edit/55

now i want to put this link in my suppliers listing page and it must be look like as follows after encryption

e.g http://localhost/asjkhjks897asfjkhas675

means I have to encrypt whole link except the domain name part.

and when anybody click on it then on server part it must be decrpted into original one so that it can be excuted like controller as suppliers and method as editAction and ID as 55 (http://localhost/suppliers/edit/55)

Thanks

Interesting problem you have to solve there!

Here are some hints that can help you in the process. Don't have much time to do a complete solution because I'm at work.

What you basicaly have to do is:

1) Create a function/component which generates the encoded urls. Something like below:

$base = $this->config->site->url; // http://www.website.com/
$url = $this->url->get(['controller' => 'news', 'action' => 'view', 'id' => 3]); // http://www.website.com/news/view/3
$uri = explode($base, $url);
$uri = array_pop($uri); // news/view/3

$uriEncoded = \Helpers\Common::encodeString($uri); // mbDCG64IK1f7wx4dCI3l1NuMSGUAaY44ekuANNXaZsGoZK4DAC-_IpajJQFyZIEb-3Q55iO3w4YYV4RSKUEb8A==
$uriDecoded = \Helpers\Common::decodeString($uriEncoded); // news/view/3 

I'm using Phalcon's Crypt class. Please note that encodeString will always generate a different value, which adds an extra layer of security. If you want same strings always, you have to use some other two-way encoding mechanism. See the encode functions below*.

2) Update your service file where you define the router. Catch the encoded string, decode it and pass to router;

3) You have to do some customizations of your app, but should not be much work.

*Encode functions:

private static $cryptKey = 'i$4^&/:%[email protected]<@{(e=*!<7u|rI~0';

/**
 *  Generate url safe encoded string
 *
 *  @param string $string string to be encoded
 *  @return encoded string
 */
public static function encodeString($string)
{
    $crypt = new \Phalcon\Crypt();
    return $crypt->encryptBase64($string, self::$cryptKey, true);
}

/**
 *  Decode string generated with Common::encodeString()
 *
 *  @param string $string Encoded string
 *  @return decoded string
 */
public static function decodeString($string)
{
    $crypt = new \Phalcon\Crypt();
    return $crypt->decryptBase64($string, self::$cryptKey, true);
}

Dear Nikolay Mihaylov,

Thanks for your valuable reply. Encryption, decription is not an issue for me. My problem is to assign values from decrypted url to concerned controller, action and parameters because I have to take many decisions based on controller name and action name.

Suppose whenever any person hit on url http://localhost/asdhakjsh908ajkhf3, it will first decrypt it to supplers/edit/55 and reqeust will automatically load the supplier controller and execute the editAction with 55 as id



69.6k
Accepted
answer
edited Dec '16

I think I found even simplier solution for you. In my example I will use my encode functions, but you can easily replace with yours.

1) We define our route, in this method we will forward to the Encoded route.

$router->add('/{encoded}', 'Homepage::index')->setName('page');

In my case I've encoded news/view/10. So my encoded URL will look like:

http://www.com/2W2jrY3UyDXd3u7U81T-E3d9YPiQIvoP54o3W6N-_GjKeOjXaJGvSgSOh1DWTspjnPJtJMYCt4GU_ma0rlbQHA==

2) Controller code:

class HomepageController extends BaseController
{
    public function indexAction()
    {   
        $decoded = \Helpers\Common::decodeString($this->dispatcher->getParam('encoded'));
        $urlParts = explode('/', $decoded);

        // You can think of better solution for handling your params depending on your routes!
        $dispatcherParams = [];  
        if (isset($urlParts[0])) {
            $dispatcherParams['controller'] = $urlParts[0]; 
        }
        if (isset($urlParts[1])) {
            $dispatcherParams['action'] = $urlParts[1];
        }   
        if (isset($urlParts[2])) {
            $dispatcherParams['id'] = $urlParts[2];
        }   
        if (isset($urlParts[3])) {
            $dispatcherParams['params'] = [$urlParts[3]];
        }  

        // Make forward to the desired action
        $this->dispatcher->setParams($dispatcherParams); // VERY IMPORTANT or you will see old dispatcher params in next page!!!
        return $this->dispatcher->forward($dispatcherParams);

3) Finally our desired page code:

class NewsController extends BaseController
{
    public function viewAction()
    {
        d($this->dispatcher->getParams());

//    Array
//    (
//        [controller] => news
//        [action] => view
//        [id] => 10
//    )     
    }
}
edited Dec '16

@Degiovanni he does not want actual url news/view/5 to be viewed by the user.

Url shorteners redirect to actual url.

Dear Nikolay Mihaylov,

Thanks for your response. Your answer sorted out my problem.