laravel報錯:TokenMismatchException in VerifyCsrfToken.php

來源:互聯網
上載者:User

      這個錯誤是剛學習Laravel的時候碰到的,只是當時還沒開始寫部落格,一直也沒記錄下來,今天下午又碰到了這個問題,趁著這會兒沒啥事,趕緊總結下。 一、為什麼報這個錯誤

答:這是由於laravel架構內建的csrf_token防護中介軟體的原因。這個中介軟體的位置在/app/middleware/VrifyCsrfToken.php。這個中介軟體的作用就是為了過濾Post請求。

      Laravel自動為每個使用者Session產生了一個CSRF Token,該Token可用於驗證登入使用者和發起要求者是否是同一人,如果不是則請求失敗。Laravel提供了一個全域協助函數csrf_token(本地存放在D:\www\laravel5.1\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php)來擷取該Token值。 二、什麼是csrf防護

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

從我們程式員的角度來看的話,請參考下面這個連結:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html 三、如果避免這個錯誤。

1、在post方式提交表單的時候,加上laravel內建的全域協助函數csrf_token。

<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">

      這段代碼的意思是在提交表單的時候,會自動帶上laravel產生的csrf_token()的值,然後在訪問路由的時候,laravel會判斷這個值,失敗則報錯:TokenMismatchException,成功則正常訪問路由。

2、如果進行ajax的post請求的時候並沒有提交form,表單,此時我們可以通過在meta中寫入一些屬性來金星csrf防護。

<head>    <title>Laravel</title>    <meta name="csrf-token" content="{{ csrf_token() }}"></head>

在ajax中,我們需要加上header屬性:

 $.ajax({        headers: {          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')        },        url: "{{url('/rsa_post')}}",        type: "post",        dataType: "json",

這樣,我們就可以正確的訪問路由了。

以上兩種方法我都試了一下,絕對是沒問題的,可以有效避免錯誤。 四、當我們不想啟用架構內建的csrf防護的時候

進入:laravel/app/Middleware/VerifyCsrfToken.php
1、找到csrf的中介軟體,然後可以按照我下面的代碼來修改

 public function handle($request, Closure $next)  {    // 使用CSRF    return parent::handle($request, $next);    // 禁用CSRF    //return $next($request);  }

當使用CSRF的時候,選用上面的代碼。當禁用的時候,選用下面的代碼。

2、有的時候我們既需要開啟CSRF防護,又需要在一些特性的post請求時不帶csrf_token(),怎麼辦。

答:laravel架構為我們提供了一個特殊的屬性,如下所示:

class VerifyCsrfToken extends BaseVerifier{    /**     * The URIs that should be excluded from CSRF verification.     *     * @var array     */    protected $except = [        //      'upload',      'rsa_post',    ];/*  public function handle($request, Closure $next)  {    // 使用CSRF    return parent::handle($request, $next);    // 禁用CSRF    //return $next($request);  }*/}

      這段代碼的意思是利用 except來進行路由過濾。在我們 except來進行路由過濾。在我們except中的是我們不想被防護的路由名稱。此處的’upload’和’rsa_post’,都是我需要post方式訪問的路由。大家可以自己試一下,經過測試,這種方式是完全沒問題的。 五、laravel實現CSRF防護的原始碼解析。

1、原始碼位置:
      由中介軟體中的代碼可知,laravel是通過中介軟體的handle()方法進行防護的。有IDE的同學可以直接追蹤下該函數。沒有用IDE編輯器的同學可以通過一定的路徑來訪問源碼。
路徑:laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCrsfToken.php
源碼如下:

 public function handle($request, Closure $next)    {        if (            $this->isReading($request) ||            $this->runningUnitTests() ||            $this->shouldPassThrough($request) ||            $this->tokensMatch($request)        ) {            return $this->addCookieToResponse($request, $next($request));        }        throw new TokenMismatchException;    }

這裡大家可以根據源碼中的幾個方法來瞭解laravel的防護機制

2、源碼分析:

1)首先Laravel開啟Session時會產生一個token值並存放在Session中(Illuminate\Session\Store.php第90行start方法),對應源碼如下:

public function start(){    // 讀取session    $this->loadSession();    if (! $this->has('_token')) {        $this->regenerateToken();    }    return $this->started = true;}

2)然後重點分析VerifyToken中介軟體的handle方法,該方法中先通過isReading方法判斷請求方式,如果要求方法是HEAD、GET、OPTIONS其中一種,則不做CSRF驗證;

3)再通過shouldPassThrough方法判斷請求路由是否在$excpet屬性數組中進行了排除,如果做了排除也不做驗證;

4)關於這個runningUnitTests()方法,我也不太明白這個是幹嘛的。後來通過百度,大致知道了這個函數是為了檢測laravel項目的運行環境的。如果是’cli’啟動的話,則正常。

5)最後通過tokensMatch方法判斷請求參數中的CSRF TOKEN值和Session中的Token值是否相等,如果相等則通過驗證,否則拋出TokenMismatchException異常。

對應源碼如下:

public function handle($request, Closure $next){    if ($this->isReading($request) || $this->shouldPassThrough($request) || $this->tokensMatch($request)) {        return $this->addCookieToResponse($request, $next($request));    }    throw new TokenMismatchException;}

以上都是laravel關於CSRF防護的內容。果然不懂的時候看源碼才是王道啊。

end

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.