session和cookie機制及laravel框架下相關應用

1、cookie的由來

  當用戶訪問某網站時,web服務器會將部分信息保存到本地計算機上,當用戶再次關顧該網站時,服務器會去查看用戶是否登陸過該網站,若是登陸過,就會將這些記錄在本地的信息發送到網頁上展現出來,這就是cookie存在的意義。php

  那麼服務器如何識別用戶呢?衆所周知,http協議是無狀態鏈接,所謂無狀態鏈接是指瀏覽器每次向服務器發起請求的時候,不是經過一個鏈接,而是每次都創建一個新的鏈接。若是是一個鏈接的話,服務器進程中就能保持住這個鏈接而且在內存中記住一些信息狀態。而每次請求結束後,鏈接就關閉,相關的內容就釋放了,因此記不住任何狀態,成爲無狀態鏈接。基於http協議的服務器,針對於不一樣的鏈接,服務器沒法識別這些鏈接都出自同一個用戶隻手,因而cookie應運而生。html

  當第一次訪問服務器時,http報文中是沒有cookie的,這時服務器在響應(response)下行HTTP報文中,命令瀏覽器攜帶cookie信息;瀏覽器再訪問同一個域的時候,將把cookie信息攜帶到請求(request)上行HTTP請求中,從而實現了HTTP模擬有了狀態。laravel

  總結一下,cookie其實是一小段的文本信息。客戶端請求服務器,若是服務器須要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還能夠根據須要修改Cookie的內容。web

2、cookie的內容及特色

  cookie主要內容:名字、值、域、路徑和過時時間redis

  1. Name和Value屬性由程序設定,默認值都是空引用
  2. Domain屬性的默認值爲當前URL的域名部分,無論發出這個cookie的頁面在哪一個目錄下的
  3. Path屬性的默認值是根目錄,即 」/」 ,無論發出這個cookie的頁面在哪一個目錄下的。能夠由程序設置爲必定的路徑來進一步限制此cookie的做用範圍
  4. Expires屬性,這個屬性設置此Cookie 的過時日期和時間

  當Expires屬性未設置時,瀏覽器網頁關閉後,cookie自動消失,稱之爲會話cookie,會話cookie存在於內存中,而非本地的硬盤裏;若設置了過時時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過時時間。存儲在硬盤上的cookie能夠在瀏覽器的不一樣進程間共享。segmentfault

cookie特色:數組

  • cookie不加密,能夠隨意篡改,所以很不安全
  • 不一樣域之間不能共享cookie
  • cookie大小受到限制,以下圖所示

clipboard.png

3、session的出世

  爲了彌補cookie不安全性這一致命缺點,session的機制產生了,session是另外一種記錄客戶狀態的機制,不一樣的是cookie保存在客戶端瀏覽器中,而session保存在服務器上。客戶端瀏覽器訪問服務器的時候,服務器把客戶端信息以某種形式記錄在服務器上,這就是session。瀏覽器

  當用戶鏈接服務器時,服務器都會創建一個session,服務器經過session_id來識別是哪一個用戶訪問。當用戶創建一次會話(session)時,能夠在用戶受權成功時給他一個惟一的cookie,當一個用戶提交了表單時,瀏覽器會將用戶的SessionId自動附加在HTTP頭信息中,當服務器處理完這個表單後,將結果返回給SessionId所對應的用戶。緩存

  總結一下,session是通過加密的,比cookie更安全,session的建立流程以下:當爲客戶端請求建立session時,服務器首先檢查請求中是否含有session_id,若是有,則服務器會在將session_id檢索出來,若是服務器沒有存儲session_id,則建立一個session_id;若是沒有,則爲此客戶端建立一個session而且生成一個與此session相關聯的sessionId,sessionId的值是一個既不會重複,又不容易被找到規律以仿造的字符串,這個sessionId將被在本次響應中返回給客戶端保存。安全

4、cookie與session的異同

  不少人說cookie和session就是一回事兒,區別在於用戶是否可見。我也比較認同此觀點,做爲session的載體,cookie保存於本地瀏覽器中,易操做,易存儲,可有效的提升服務器性能(不佔內存),但cookie有明文不安全,大小受限制等缺點; session保存於服務器緩存中,加密,session_id大小不受限制,但影響服務器性能。

  說到cookie和session的聯繫,就不得不提到禁用cookie了,在客戶端瀏覽器設置裏,用戶是能夠禁用cookie的,由於cookie是session_id的載體,因此一旦cookie被禁用,那麼session也就沒法使用。可是有兩種方法能夠解決依賴問題,其一是URL重寫,簡單的說就是在url地址中加入session_id參數,其二是表單隱藏字段,服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時可以把session_id傳遞迴服務器,以下所示:

clipboard.png

  另外一個聯繫是session共享,對於多網站(同一父域不一樣子域)單服務器,咱們須要解決的就是來自不一樣網站之間session_id的共享。因爲域名不一樣(aaa.test.com和bbb.test.com),而session_id又分別儲存在各自的cookie中,所以服務器會認爲對於兩個子站的訪問,是來自不一樣的會話。解決的方法是經過修改cookies的域名爲父域名達到cookie共享的目的,從而實現session_id的共享。帶來的弊端就是,子站間的cookie信息也同時被共享了。

5、laravel下的相關應用

session應用

  在config/session.php中配置以下:

'driver' => env('SESSION_DRIVER', 'file'),
    'lifetime' => 120,
    'expire_on_close' => false,
    'encrypt' => false,
    'files' => storage_path('framework/sessions'),
    'connection' => null,
    'table' => 'sessions',
    'lottery' => [2, 100],
    'cookie' => 'laravel_session',
    'path' => '/',
    'domain' => null,
    'secure' => false,
];

  driver配置項用於設置Session存儲方式,默認是file,即存儲在文件中,該文件位於files配置項配置的路徑,即storage/framework/sessions。此外Laravel還支持其它存儲方式:

  • database:將Session數據存放到指定數據表中,該數據表由配置項table設置
  • memcached:將Session數據存放到Memcached中
  • redis:將Session數據存放到Redis中
  • array:將Session數據存放到數組中,該配置僅用於測試環境要修改driver配置,須要去項目根目錄下.env文件修改其中的SESSION_DRIVER選項。

lifetime配置項用於設置Session有效期,默認爲120分鐘。
expire_on_close配置項用於設置是否在瀏覽器關閉時當即讓Session失效。
encrypt配置項用於配置Session數據是否加密。
lottery配置項用於配置回收Session存放位置。
cookie配置項用於配置存放Session ID的Cookie名稱,默認是laravel_session。
path配置項用於配置存放Session ID的Cookie存放路徑,默認爲項目根目錄。
domain配置項用於配置存放Session ID的Cookie存放域名。
secure配置項用於配置是否只有在HTTPS協議下發送Session ID到服務器。

使用session函數

session(['site.xxx'=>'LaravelAcademy.org']);
$site = session('site');
dd($site);

clipboard.png

使用request請求

咱們能夠以這種方式獲取全部Session數據:

$sessions = $request->session()->all();

咱們能夠像這樣存取Session數據:

$request->session()->put('site', 'http://LaravelAcademy.org');
if($request->session()->has('site')){
    $site = $request->session()->get('site');
    dd($site);
}

此外還能夠這樣獲取Session數據(若是對應Session不存在,返回默認值):

$sitename = $request->session()->get('sitename','Laravel學院');
dd($sitename);

此外還可使用push方法推送多個數據到Session數組:

$request->session()->push('site.xxx', 'http://LaravelAcademy.org');
$request->session()->push('site.xxx', 'Laravel學院');
if($request->session()->has('site')){
    $site = $request->session()->get('site');
    dd($site);
}

clipboard.png

使用pull方法,獲取數據後刪除
使用flush方法,一次性刪除全部session數據
使用forget方法,刪除某個session數據

一次性session

若是想保證一次性Session數據有效,能夠定義TestController@sessionx代碼以下:

public function sessionx(Request $request){
    $request->session()->reflash();
    $message = session('message');
    echo $message;
}

這樣無論怎麼刷新Session數據始終有效。此外還能夠指定哪些Session數據有效:

$request->session()->keep(['message']);

你們也能夠自行編譯laravel代碼:

class Middleware implements HttpKernelInterface
{
    ...
    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
    {
        $this->checkRequestForArraySessions($request);
        if ($this->sessionConfigured()) {
            $session = $this->startSession($request); // 啓動session
            $request->setSession($session);
        }
        $response = $this->app->handle($request, $type, $catch); // 調用controller的method
        if ($this->sessionConfigured()) {
            $this->closeSession($session);         //關閉session
            $this->addCookieToResponse($response, $session);
        }
        return $response;
    }
    ...
 
    protected function closeSession(SessionInterface $session)
    {
        $session->save();    // 保存session
        $this->collectGarbage($session);
    }
}

cookie應用

添加Cookie

例如,咱們須要在控制器中設置一個"Hello, Laravel"的cookie值,並設置有效期爲10分鐘。這裏推薦使用cookie的隊列方法Cookie::queue(),由於這樣Cookie會自動添加到響應:

<?php

namespace App\Http\Controllers;
use Cookie;
use App\Http\Controllers\Controller;

class DashboardController extends Controller
{

    public function index()
    {
        Cookie::queue('younger', 'Hello, dayang', 30);
        return view('welcome');
    }
}

獲取Cookie

Cookie的使用離不開Response和Request。獲取Cookie的值有兩個層面,一個是服務端,另外一個是客戶端。若是要服務端獲取到Cookie的值,就須要從Request中得到:

public function index(Request $request)
{
    $cookie = $request->cookie('younger');
    dump($cookie);
}

若是想得到全部Cookie的值,可使用不傳參數的方法:

public function index(Request $request)
{
    $cookies = $request->cookie();
    dump($cookies);
}

清除Cookie

清除Cookie的方法比較簡單,原理和設置Cookie同樣的,只是將過時時間設置成了過去。這裏也須要將Cookie加入到HTTP的Response中,使用make()或者forget()方法都可:

方式一:
 \Cookie::queue(\Cookie::forget('younger'));
或 \setcookie('younger', '', -1, '/');
方式二:
$cookie = Cookie::forget('younger');
//return Redirect::route('index')->withCookie($cookie);

參考博文

https://segmentfault.com/a/11...
http://www.cnblogs.com/endles...
http://blog.csdn.net/sundache...
http://blog.csdn.net/proglove...
https://www.zhihu.com/questio...
http://laravelacademy.org/pos...
http://www.cnblogs.com/phpper...

相關文章
相關標籤/搜索