CSRF(Cross-site request forgery跨站請求僞造,也被稱爲「One Click Attack」或者Session Riding,一般縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS很是不一樣,而且攻擊方式幾乎相左。XSS利用站點內的信任用戶,而CSRF則經過假裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊每每不大流行(所以對其進行防範的資源也至關稀少)和難以防範,因此被認爲比XSS更具危險性。php
Yii2 中的CSRF配置html
Yii2 默認是啓用CSRF令牌驗證ajax
配置在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. 在要取消的控制器中添加:cookie
public $enableCsrfValidation = false;
2. 在配置中取消enableCookieValidation的驗證app
'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
1. 使用Yii掛件生成html網站
這樣會自動生成帶有隱藏表單的_csrfui
<?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" >
使用原生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); }
數據庫表的結構被緩存了
執行:
//清理全部表結構緩存數據 Yii::$app->db->getSchema()->refresh();