与用户通信的用户和电子邮件友好链接



有时您需要发送到用户激活链接或链接到其个人资料或链接到某些可能埋入应用程序结构或文件夹结构的资产。

诱惑是快速创建这样的链接:

http://example.com/index.php?controller=users&action=activate&profile_id=123023&token=a2ad2a1adaawda&goto=user_profile

如果您在html页面上显示该链接,在<A>元素后面,一切都可以,但是如果您需要通过电子邮件将此链接发送给您遇到的一些麻烦的用户。

如果您很幸运,并且用户的电子邮件客户端呈现HTML,则可以将其隐藏在<A>后面。否则,您必须将其作为纯文本发送,并且它可能会被分为多行或仅通过电子邮件客户端进行部分单击,从而使用户单击它感到沮丧,或将其复制/粘贴到浏览器中。<<<<<<<<<<

该解决方案是什么?

我最近详细介绍了我最近如何解决了这个问题,也欢迎其他解决方案。

这个问题的答案是用php,cakephp和apache mod_rewrite编写的,但此处的原理也可以应用于其他Web平台。

我最终使用的解决方案是利用cakephp中的路由器(如果缺少的话,只需使用apace中的mod_rewrite,通常是通过编辑.htaccess文件)。

建议:使用短URL

这里的基本原则是在与用户的通信(尤其是在电子邮件中)中使用非常短的链接,看起来不错,并且不到80个字符(如果可能)以避免包装。

因此,而不是发送真正较长且丑陋的URL:

http://example.com/index.php?controller=users&action=activate&profile_id=123023&token=a2ad2a1adaawda&goto=user_profile

发送类似:

http://example.com/activate_a2dra2bc430a11af

这要短得多,并且很可能在电子邮件客户端中正确渲染,如果不容易复制/粘贴。

那么我们如何在两个之间来回转换。

解决方案因您选择的平台而异。

如果您没有路由器实现,则必须依靠.htaccess配置将短URL转换为相应的长URL。

但是,如果您使用诸如cakephp之类的东西(或者如果您实现自己的路由器),则在格式化链接的方式方面具有更大功能(否则这将很难或不可能配置apache的mod_rewrite)。

这是我如何实现

首先,我已经连接了一条路由(routes.php),该路由将拦截我的简短激活链接:

Router::connect( '/activate_:token', 
    array( 'controller' => 'users', 'action' => 'activate' ),
    array( 'pass' => array( 'token' ), 'token' => '(.*)' ) 
);

在我的用户控制器中,我具有此功能(一般概述了您需要做的事情):

public function activate( $token ){
    //TODO: 1. validate $token has expected format
    //TODO: 2. do a db backup to check this token is valid
    //TODO: 3. do required action (like mark user as active)
    //TODO: 4. if this is 'use once' then delete token from database to prevent further use of link
    //TODO: 5. redirect user to the appropriate location in your app
}

以下是控制器动作的简短说明。

令牌以前是独特的,并存储在数据库中。根据您的需求,您可以为此使用令牌模型,或者只需在用户表中使用token列(就像我一样)。

步骤1:验证令牌。确保令牌看起来像一个令牌是个好主意。例如,如果您仅期望数字或十六进制值,请对此进行验证!

步骤2:执行DB查找以使用令牌找到行。这将有助于两件事:首先,您将确保这是您发送的令牌,其次:它还可以找到链接到的用户!(如果您将令牌存储在用户表中或通过加入)。

步骤3:做您需要做的事情。就我而言,我已经激活了用户,但是您可以做任何事情:重置密码,增加计数器,发送其他通知...

步骤4:如果这是只能使用一次的链接,现在是从DB中删除令牌的好时机。这将确保链接无法再次工作。

步骤5:根据您的操作类型,将用户重定向到应用程序中的正确位置。在我的情况下,用户个人资料。

令牌生成

正如我所说的,为了使工作代币必须是唯一的。有很多方法可以做到这一点,具体取决于您的令牌需要的安全性,但是在大多数情况下,类似这样的简单作用将起作用(CakePHP代码):

while( 1 ){
    $token = substr( md5( Configure::read( 'Security.salt' ) . rand(1,10000) . time() ), 0, 16 );
    //repeat until I get a unique token. You will most likely get a unique one from the first time!
    if( !token_exists( $token ) ){
        break;
    }
}

在结论中

使用这样的令牌:

  • 缩短URL,使它们成为电子邮件和用户友好
  • 增加了一些安全性。猜测有效的令牌比在原始长URL中的获取参数
  • 中更难
  • 这很容易扩展到永久链接和其他动作

我希望您发现这种内容丰富且有用,并给您一些想法!

参考:

  • cakephp(感谢您的路由器实现!)
  • apache mod_rewrite

最新更新