• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Yii2框架的csrf验证原理分析及token缓存解决方案

php 搞代码 4年前 (2022-01-21) 15次浏览 已收录 0个评论

本文主要分三个部分,首先简单介绍csrf,接着对照源码重点分析一下yii框架的验证原理,最后针对页面缓存导致的token被缓存提出一种可行的方案。涉及的知识点会作为附录附于文末。感兴趣的朋友了解一下吧。

1.CSRF描述

CSRF全称为“Cross-Site Request Forgery”,是在用户合法的SESSION内发起的攻击。黑客通过在网页中嵌入Web恶意请求代码,并诱使受害者访问该页面,当页面被访问后,请求在受害者不知情的情况下以受害者的合法身份发起,并执行黑客所期待的动作。以下HTML代码提供了一个“删除产品”的功能:

<a href="http://www.shop.com/delProducts.php?id=100" "javascript:return confirm('Are you sure?')">Delete</a>

假设程序员在后台没有对该“删除产品”请求做相应的合法性验证,只要用户访问了该链接,相应的产品即被删除,那么黑客可通过欺骗受害者访问带有以下恶意代码的网页,即可在受害者不知情的情况下删除相应的产品。

2.yii的csrf验证原理 /vendor/yiisoft/yii2/web/Request.php简写为Request.php

/vendor/yiisoft/yii2/web/Controller.php简写为Controller.php

开启csrf验证

在控制器里将enableCsrfValidation为true,则控制器内所有操作都会开启验证,通常做法是将enableCsrfValidation为false,而将一些敏感操作设为true,开启局部验证。

public $enableCsrfValidation = false;/** * @param \yii\base\Action $action * @return bool * @desc: 局部开启csrf验证(重要的表单提交必须加入验证,加入$accessActions即可 */public function beforeAction($action){    $currentAction = $action->id;    $accessActions = ['vote','like','delete','download'];    if(in_array($cur<a>本2文来*源gao($daima.com搞@代@#码(网</a><strong>搞gaodaima代码</strong>rentAction,$accessActions)) {        $action->controller->enableCsrfValidation = true;    }    parent::beforeAction($action);    return true;}

生成token字段

在Request.php

首先通过安全组件Security获取一个32位的随机字符串,并存入cookie或session,这是原生的token.

/** * Generates  an unmasked random token used to perform CSRF validation. * @return string the random token for CSRF validation. */protected function generateCsrfToken(){    $token = Yii::$app->getSecurity()->generateRandomString();    if ($this->enableCsrfCookie) {        $cookie = $this->createCsrfCookie($token);        Yii::$app->getResponse()->getCookies()->add($cookie);    } else {        Yii::$app->getSession()->set($this->csrfParam, $token);    }    return $token;}

接着通过一系列加密替换操作,生成加密后_csrfToken,这个是传给浏览器的token. 先随机产生CSRF_MASK_LENGTH(Yii2里默认是8位)长度的字符串 mask

对mask和token进行如下运算 str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask))); $this->xorTokens($arg1,$arg2) 是一个先补位异或运算

/** * Returns the XOR result of two strings. * If the two strings are of different lengths, the shorter one will be padded to the length of the longer one. * @param string $token1 * @param string $token2 * @return string the XOR result */private function xorTokens($token1, $token2){    $n1 = StringHelper::byteLength($token1);    $n2 = StringHelper::byteLength($token2);    if ($n1 > $n2) {        $token2 = str_pad($token2, $n1, $token2);    } elseif ($n1 < $n2) {        $token1 = str_pad($token1, $n2, $n1 === 0 ? ' ' : $token1);    }    return $token1 ^ $token2;}public function getCsrfToken($regenerate = false){    if ($this->_csrfToken === null || $regenerate) {        if ($regenerate || ($token = $this->loadCsrfToken()) === null) {            $token = $this->generateCsrfToken();        }        // the mask doesn't need to be very random        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.';        $mask = substr(str_shuffle(str_repeat($chars, 5)), 0, static::CSRF_MASK_LENGTH);        // The + sign may be decoded as blank space later, which will fail the validation        $this->_csrfToken = str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));    }    return $this->_csrfToken;}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Yii2框架的csrf验证原理分析及token缓存解决方案

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址