亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

yii2 csrf驗證理分析

2020-03-22 20:12:51
字體:
來源:轉載
供稿:網友
  • 知識補充

    因為yii2 csrf的驗證的加解密 涉及到異或運算

    所以需要先補充php里字符串異或運算的相關知識,不需要的可以跳過

    ^異或運算
    不一樣返回1 否者返回 0
    在PHP語言中,經常用來做加密的運算,解密也直接用^就行
    字符串運算時 利用字符的ascii碼轉換為2進制來運算
    單個字符運算
    舉例的ascii見下表

    字符

    二進制

    ASCII

    a

    1100001

    97

    b

    1100010

    98

    c

    1100011

    99

    d

    1100100

    100

    計算結果

    運算

    二進制

    ASCII

    a^b

    0000 0011

    3

    a^c

    0000 0010

    2

    b^d

    0000 0110

    6

    ab^cd

    0000 0010

    2

    a^cd

    0000 0010

    2

    ab^c

    0000 0010

    2

    1.對于單個字符和單個字符的
    直接計算其結果即可 比如表里的a^b

    2.對于長度一樣的多個字符串 如表里的ab^cd
    計算a^c對應的結果和和b^d對應的結果 對應的字符連接起來

    <?php$str1='ab';$str2='cd';$r= $str1^$str2;var_dump($r);echo '<hr>';for($i=0;$i<strlen($r) ;$i++){    echo ord($r[$i]).'<br>';}?>

    對于不等的
    以短的字符串長度位進行計算

    Yii2的csrf token驗證
    在yii2的接收post請求時
    在如果開啟
    enableCsrfValidation為true
    在/vendor/yiisoft/yii2/web/Controller.php

    <?php   html' target='_blank'>public function beforeAction($action)    {        if (parent::beforeAction($action)) {            if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) {                throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));            }            return true;        }                return false;    }?>

    會進行validateCsrfToken驗證
    在/vendor/yiisoft/yii2/web/Request.php

    <?phppublic function validateCsrfToken($token = null)    {        $method = $this->getMethod();        // only validate CSRF token on non-'safe' methods http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1        if (!$this->enableCsrfValidation || in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {            return true;        }        $trueToken = $this->loadCsrfToken();        if ($token !== null) {            return $this->validateCsrfTokenInternal($token, $trueToken);        } else {            return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken)                || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken);        }    }?>

    說明在 GET, HEAD, OPTIONS 均不驗證,除了這幾種主要用的也就post了

    說明在我們發送post請求時必須發送相關驗證的字段和值
    下面看CsrfToken產生過程
    在/vendor/yiisoft/yii2/web/Request.php里

    <?phppublic 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;    }?>

    會發現
    _csrfToken的產生大致如下
    如果開啟了enableCsrfCookie,
    CsrfToken就從cookie里取,否者從session里取(更安全)
    可在
    /vendor/yiisoft/yii2/web/Request.php的下面部位看到

    <?php protected function loadCsrfToken()    {        if ($this->enableCsrfCookie) {            return $this->getCookies()->getValue($this->csrfParam);        } else {            return Yii::$app->getSession()->get($this->csrfParam);        }    }?>

    從loadCsrfToken()里取出的值這里稱token

    在post里發送的也就是Yii::$app->getRequest()->csrfParam 這里稱csrfToken現在根據代碼大致說下生成和驗證的主要思路,當然自己看代碼更能細致的了解1.從cookie或者session里取出token ,當然cookie或者session里如果沒有就是初始化操作的過程了,這里初始化不是重點2.隨機產生CSRF_MASK_LENGTH(Yii2里默認是8位)長度的字符串 mask3.對mask和token進行如下運算str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));$this->xorTokens($arg1,$arg2) 是一個先補位異或運算

    傳入$arg1,$arg2
    長度短的要用自身補到長度長的字符串的位置
    見代碼部分
    在/vendor/yiisoft/yii2/web/Request.php 的如下部分

     <?php  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;    } ?>

    就是說如果 $arg1比$arg2短,$arg1要用自身補齊 補到和和$arg2一樣的長度
    這里為什么要這樣做?
    因為在php里
    'a'^'bc' 會只算 a^b 而不考慮c了,這里采用了向長度更長的來補
    如果用
    xorTokens來處理 'a'和'bc'
    會先把a用自己填充到和bc一樣的長度后再進行異或運算
    異或運算詳見上文補充

    str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));


    計算后即會得出在post請求時要發送的值 csrfToken

    下面是驗證過程
    1.根據 表單字段名
    Yii::$app->getRequest()->csrfParam;
    從post里拿到
    csrfToken的值
    從方法 validateCsrfToken里可以看到
    代碼
    在/vendor/yiisoft/yii2/web/Request.php 的如下部分

    <?php public function validateCsrfToken($token = null)    {        $method = $this->getMethod();        // only validate CSRF token on non-'safe' methods http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1        if (!$this->enableCsrfValidation || in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {            return true;        }        $trueToken = $this->loadCsrfToken();        if ($token !== null) {            return $this->validateCsrfTokenInternal($token, $trueToken);        } else {            return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken)                || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken);        }    }?>

    $this->getBodyParam($this->csrfParam)
    可以看出
    解密的目的就是要從
    csrfToken里取出token 然后和會話里的token比較
    見/vendor/yiisoft/yii2/web/Request.php 的如下部分

    <?php private function validateCsrfTokenInternal($token, $trueToken)    {        $token = base64_decode(str_replace('.', '+', $token));        $n = StringHelper::byteLength($token);        if ($n <= static::CSRF_MASK_LENGTH) {            return false;        }        $mask = StringHelper::byteSubstr($token, 0, static::CSRF_MASK_LENGTH);        $token = StringHelper::byteSubstr($token, static::CSRF_MASK_LENGTH, $n - static::CSRF_MASK_LENGTH);        /*          注意此時的$token在加密過程中是xorTokens($trueToken,$mask)的結果        */        $token = $this->xorTokens($mask, $token);        return $token === $trueToken;    }?>

    加密時用的是
    str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));
    解密
    1.首先要把.替換成+
    2.然后base64_decode
    再 根據長度分別取出$mask和$this->xorTokens($token, $mask) ;
    為了說明方便 $this->xorTokens($token, $mask) 這里稱作 token1
    然后
    進行mask和token1的異或運算,即得token
    注意在加密時
    token1=token^mask
    所以
    解密時
    token=mask^token1=mask^(token^mask)

    yii2
    中的核心思路
    token是從會話中取得的
    用隨機串和token進行運算處理 得到一個加密串
    驗證的時候通過這個加密串解密出來這個token和會話里的值進行比較

    PHP編程

    鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
    国产视频精品自拍| 久久久999精品免费| 国产精品自产拍高潮在线观看| 午夜精品久久久久久久久久久久久| 国精产品一区一区三区有限在线| 亚洲人成网站色ww在线| 国产综合在线观看视频| 国产剧情久久久久久| 日本中文字幕不卡免费| 久久久久久伊人| 国产在线观看一区二区三区| 国产精品96久久久久久又黄又硬| 亚洲图片制服诱惑| 久久视频在线直播| 久久夜色精品亚洲噜噜国产mv| 国产欧美一区二区三区视频| 亚洲男人天堂手机在线| 亚洲一区中文字幕在线观看| 色一情一乱一区二区| 欧美午夜美女看片| 91午夜理伦私人影院| 欧美激情视频在线免费观看 欧美视频免费一| 98视频在线噜噜噜国产| 亚洲国产高清高潮精品美女| 亚洲色在线视频| 亚洲精品一区二区在线| 中文字幕久久久av一区| 精品国产一区二区三区久久| 国产又爽又黄的激情精品视频| 日韩欧美中文字幕在线播放| 色中色综合影院手机版在线观看| 久久激情视频免费观看| 国产精品入口日韩视频大尺度| 福利一区视频在线观看| 色偷偷av一区二区三区| 全亚洲最色的网站在线观看| 亚洲自拍偷拍网址| 国产亚洲欧美日韩美女| 国产亚洲欧美日韩一区二区| 日韩亚洲成人av在线| 麻豆一区二区在线观看| 奇米4444一区二区三区| 最近2019年日本中文免费字幕| 欧美精品免费看| 91精品国产综合久久香蕉922| 丝袜情趣国产精品| 日韩成人中文字幕| 欧美成人亚洲成人日韩成人| 亚洲美女视频网站| 亚洲丁香婷深爱综合| 国产精品天天狠天天看| 中文字幕在线亚洲| 国产美女精彩久久| 国产欧美精品一区二区| 国外色69视频在线观看| 麻豆成人在线看| 久久久久久免费精品| 亚洲第一区第二区| 亚洲欧美日韩中文在线| 国产精品美女免费| 日本乱人伦a精品| 欧美精品一区二区三区国产精品| 日韩高清免费观看| 欧美孕妇孕交黑巨大网站| 日韩在线视频观看正片免费网站| 国产91精品不卡视频| 久久香蕉国产线看观看网| 精品一区二区三区四区| 精品久久久久久久久久久久| 日韩欧美中文免费| 91九色综合久久| 亚洲影视中文字幕| 亚洲女人天堂成人av在线| 亚洲国产天堂久久综合| 久久精品国产免费观看| 精品久久久久久久久久久久| 欧美贵妇videos办公室| 国产欧美日韩亚洲精品| 欧美成人黑人xx视频免费观看| 国产精品国产自产拍高清av水多| 亚洲成人激情在线观看| 秋霞av国产精品一区| 亚洲视频欧美视频| 国产欧美日韩专区发布| 91在线观看免费观看| 国产精品999999| 国产精品偷伦视频免费观看国产| 色综合久久精品亚洲国产| 国产欧美一区二区三区在线| 欧美激情在线一区| 日韩欧美极品在线观看| 国产精品一二区| 亚洲最大av网| 国产精品第3页| 日韩男女性生活视频| 国产91精品久久久久| 91成人在线视频| 一本色道久久88亚洲综合88| 青青久久aⅴ北条麻妃| 国产精品久久二区| 国产区亚洲区欧美区| 成人美女免费网站视频| 欧美老女人xx| 亚洲电影免费观看高清完整版在线| 亚洲网站视频福利| 久久亚洲精品一区二区| 国产精品久久久久久久久影视| 91香蕉嫩草神马影院在线观看| 日韩欧美在线播放| 亚洲欧美国产一区二区三区| 久久精品成人欧美大片| 日韩成人中文字幕在线观看| 久久精品久久精品亚洲人| 成人午夜在线观看| 亚洲欧美另类人妖| 久久精品一偷一偷国产| 久久天天躁狠狠躁夜夜av| 亚洲福利视频在线| 欧美成人一二三| 欧美日韩在线看| 91影院在线免费观看视频| 色老头一区二区三区在线观看| 97人洗澡人人免费公开视频碰碰碰| 国产精品久久视频| 亚洲天堂久久av| 97精品一区二区三区| 国产91热爆ts人妖在线| 久久精品男人天堂| 91精品国产99| www.99久久热国产日韩欧美.com| 欧美视频13p| 美日韩精品免费视频| 欧美日韩免费在线| 国产精品wwww| 国产免费一区二区三区在线能观看| 欧美三级欧美成人高清www| 日韩亚洲精品视频| 欧美激情按摩在线| 日韩欧美国产激情| 久久韩剧网电视剧| 亚洲深夜福利视频| 日韩精品亚洲视频| 欧美中文在线免费| xxx欧美精品| 中文国产亚洲喷潮| 欧美一区亚洲一区| 26uuu日韩精品一区二区| 亚洲电影免费观看高清| 91精品视频播放| 美女精品视频一区| 日韩欧美在线视频日韩欧美在线视频| 亚洲国产高清自拍| 亚洲精品mp4| 亚洲成色www8888| 久久伊人免费视频| 久久av在线看| 欧美伦理91i| 2019中文字幕在线观看| 国内久久久精品| 亚洲自拍小视频| 97精品免费视频| 国产精品户外野外| 亚洲电影免费观看高清完整版在线| 日韩国产精品视频|