解決Yii2 啟用_csrf驗證后POST數據仍提示“您提交的數據無法驗證”


 

一 CSRF 概念

CSRF(Cross-site request forgery跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,並且攻擊方式幾乎相左。XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防范的資源也相當稀少)和難以防范,所以被認為比XSS更具危險性。

 

Yii2 中的CSRF配置

Yii2 默認是啟用CSRF令牌驗證

配置在main.php中:

'components' => [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'enableCookieValidation' => true,
            'cookieValidationKey' => 'cookvalid',
        ],
      …………

若要取消CSRF驗證有兩種方法

1. 在要取消的控制器中添加:

public $enableCsrfValidation = false;

2. 在配置中取消enableCookieValidation的驗證

'components' => [
        'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
            'enableCookieValidation' => false,
            'cookieValidationKey' => 'cookvalid',
        ],
    …………

 

二 啟用CSRF的 POST驗證

 當啟用了csrf后, 所有表單POST提交的數據就會進行驗證,在表單中添加CSRF有兩種方法

1. 使用Yii掛件生成html

這樣會自動生成帶有隱藏表單的_csrf

<?php
                    $form = ActiveForm::begin([
                                'id' => 'login-form',
                    ]);
                    ?>
                    <input type="hidden" name="jfinal_token" value="${jfinal_token }" />
                    <div class="form-group">
                        <label for="j_username" class="t">用戶名:</label> 
                        <?php echo Html::input('type', 'LoginForm[username]', $model->username, ['class' => 'form-control x319 in', 'placeholder' => 'Username', 'autocomplete' => 'off']); ?>
                    </div>
                    <div class="form-group">

                        <label for="j_password" class="t">密 碼:</label> 
                        <?php echo Html::input('password', 'LoginForm[password]', $model->password, ['class' => 'form-control x319 in', 'placeholder' => 'Password']); ?>
                    </div>
                   
                    <?php ActiveForm::end(); ?>

2. 手動添加_csrf

在form表單中手動添加隱藏表單,也適用於ajax的手動添加_csrf

<input type="hidden" value="<?php echo Yii::$app->request->csrfToken; ?>" name="_csrf" >

 

三 提交POST提示“您提交的數據無法驗證”

使用原生or Yii掛件生成html帶有_csrf 表單提交仍然提示“您提交的數據無法驗證”

表單html如下:

<div class="login_form">
    <form id="login-form" action="/default/login" method="post">
    <input type="hidden" name="_csrf" value="bDV6RjFCS0RURzcwCAwKNC5AIyIDdy19BkAOF38YGSkLGCI2UgcEMQ==">
    <div class="form-group">
        <label for="j_username" class="t">用戶名:</label> 
         <input type="type" class="form-control x319 in" name="LoginForm[username]" placeholder="Username" autocomplete="off">               
    </div>
    <div class="form-group">
    <label for="j_password" class="t">密 碼:</label> 
          <input type="password" class="form-control x319 in" name="LoginForm[password]" placeholder="Password">        
    </div>
     </form>     
</div>

_csrf 是Yii自動生成,不存在字符串不匹配

后來找到問題: 

render的時候使用了exit, 應使用return

*注: render 時也不能用echo 或 die()

解決辦法:

 return $this->render('action',['t'=>$t,'text'=>$text]);

封裝render

 return $this->display([
            't' => $t,
            'text' => $text,
        ]);



 /**
     *  render頁面
     * @param array  當$i為array模版為$this->action,數據源為$i
     * 當$i為string,模版為$i,數據源為$param
     */
    protected function display($i = array(), $param = array()) {
        $data = array();
        if (is_string($i)) {
            $tpl = $i;
            $data = $param;
        } else {
            $data = $i;
          $tpl = $this->action->id;
        }

       return $this->render(strtolower($tpl), $data);
    }

 

 

解決Yii2給數據庫表添加字段后對應模型無法識別到該屬性的原因

數據庫表的結構被緩存了

執行:

//清理所有表結構緩存數據
Yii::$app->db->getSchema()->refresh();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM