WePHP的表单令牌验证
WePHP的表单令牌验证可以有效的防止表单重复提交和一部分远程表单提交(为什么是一部分,稍后解答)。
表单令牌验证和伪静态有一处兼容问题,所以在开启伪静态时,默认访问控制器下默认访问方法禁止设置表单令牌,往往是index.php/index/index。
关闭伪静态后删除.htaccess文件的跳转,以上限制解除。
使用方法:
在C文件中调用setToken($formName,$key)方法,$formName表单的名称,注意这个名称安全起见最好不要出现在HTML的表单内,$key是对隐藏域的加密密钥,默认是常量ENKEY
1 <?php 2 class C_index extends Action{ 3 function index(){ 4 5 $this->setToken('test','WePHP'); 6 7 $this->display(); 8 } 9 }
在V文件中 {$testToken}调用隐藏域密钥,如果你有一个表单名叫zhangsan,那就用{$zhangsanToken}调用
1 <form action="index.php/index/show" method="post" > 2 {$testToken} 3 <input type="submit"> 4 </form>
V文件生成的源代码
1 <form action="index.php/index/show" method="post" > 2 <input type="hidden" name="IwAjPA8DCjstPg==" value="YlRneCQyFiQ="/> 3 <input type="submit"> 4 </form>
实例化M文件 checkToken($formName,$key),验证表单令牌函数,成功返回True ,否则False。
1 <?php 2 class C_index extends Action{ 3 function index(){ 4 5 $this->setToken('test','WePHP'); 6 7 $this->display(); 8 } 9 function show(){; 10 $mod = M('user'); 11 var_dump($mod->checkToken('test','WePHP')); 12 } 13 } 14 ?>
WePHP的表单令牌验证,对重复提交是基于SESSION的,不多解释。说说在防跨站的问题,假设我写了一个开源的CMS,那么后台添加超级用户会有一个表单。
大概如下:
1 <form action="index.php" method="post"> 2 <input name="user" type="test"/> 3 <input name="password" type="password"/> 4 <input name="submit" type="submit"/> 5 </form>
当一个超级用户登录以后,他通过这个表单,可以添加另一个超级用户,问题来了,我是开源的CMS,表单结构是暴露的,如此是不是任何一个人构造一个POST提交,都可以添加任意的超级用户。
当然你可以添加一些验证,而表单令牌就是其中之一。
1 <form action="index.php" method="post"> 2 <input type="hidden" name="IwAjPA8DCjstPg==" value="YlRneCQyFiQ="/> 3 <input name="user" type="test"/> 4 <input name="password" type="password"/> 5 <input name="submit" type="submit"/> 6 </form>
此时必须访问这个页面以后,有隐藏域的表单提交到写入端才会写入数据库,注意两个必备条件,1.访问此页面(生成SESSION)2.有隐藏域(隐藏域的值每次都是变化的),而想访问此页面必须经过CMS的登陆
验证,这也就限制了远程表单提交。
但是如果你的表单是公开访问的,那密钥理论上还是可以突破的,所以说对部分远程表单提交有效。