一、cookie的由來
當使用者訪問某網站時,web伺服器會將部分資訊儲存到本機上,當使用者再次關顧網站時,伺服器會去查看使用者是否登入過該網站,如果登入過,就會將這些記錄在本地的資訊傳送到網頁上展示出來,這就是cookie存在的意義。
那麼伺服器要如何辨識使用者呢?眾所周知,http協定是無狀態連接,所謂無狀態連接是指瀏覽器每次向伺服器發起請求的時候,不是透過一個連接,而是每次都建立一個新的連接。如果是連接的話,伺服器進程中就能保持住這個連線並且在記憶體中記住一些資訊狀態。而每次請求結束後,連線就關閉,相關的內容就釋放了,所以記不住任何狀態,變成無狀態連線。基於http協定的伺服器,針對不同的連接,伺服器無法辨識這些連接都出自同一個使用者隻手,於是cookie應運而生。
當第一次造訪伺服器時,http封包中是沒有cookie的,這時伺服器在回應(response)下行HTTP封包中,指令瀏覽器攜帶cookie訊息;瀏覽器再造訪同一個域的時候,將把cookie訊息攜帶到請求(request)上行HTTP請求中,從而實現了HTTP模擬有了狀態。
總結一下,cookie其實是一小段的文字訊息。客戶端請求伺服器,如果伺服器需要記錄該使用者狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端會把Cookie保存起來。當瀏覽器再要求網站時,瀏覽器會把請求的網址連同該Cookie一同提交給伺服器。伺服器檢查該Cookie,以此來辨識用戶狀態。伺服器也可以根據需要修改Cookie的內容。
二、cookie的內容及特點
cookie主要內容:名字、值、域、路徑和過期時間Name和Value屬性由程式設定,預設值都是空引用Domain屬性的預設值為當前URL的網域部分,不管發出這個cookie的頁面在哪個目錄下的Path屬性的預設值是根目錄,即”/” ,不管發出這個cookie的頁面在哪一個目錄下的。可以由程式設定為一定的路徑來進一步限制此cookie的作用範圍Expires屬性,這個屬性設定此Cookie 的過期日期和時間
當Expires屬性未設定時,瀏覽器網頁關閉後,cookie會自動消失,稱之為會話cookie,會話cookie存在於記憶體中,而非本地的硬碟裡;若設定了過期時間,瀏覽器就會把cookie儲存到硬碟上,關閉後再次開啟瀏覽器,這些cookie仍然有效直到超過設定的過期時間。儲存在硬碟上的cookie可以在瀏覽器的不同進程之間共用。
cookie特點:
1.cookie不加密,可以隨意篡改,因此很不安全
2.不同域之間不能共享cookiecookie大小受到限制,如下圖所示
三、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將會被傳回給客戶端保存。
四、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傳回伺服器,如下所示:
另一個聯繫是session共享,對於多網站(同一父域不同子域)單一伺服器,我們需要解決的就是來自不同網站之間session_id的共享。由於網域名稱不同(aaa.test.com和bbb.test.com),而session_id又分別儲存在各自的cookie中,因此伺服器會認為對於兩個子站的存取,是來自不同的會話。解決的方法是透過修改cookies的網域為父網域達到cookie共享的目的,從而實現session_id的共享。帶來的弊端就是,子站間的cookie資訊也同時被分享了。
五、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);
使用request請求
我們可以以此方式取得所有Session資料:$sessions = $request->session()->all();我們可以像這樣存取Session資料:
$request->session()->put('site', 'https://www.php.cn/');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', 'https://www.php.cn/');$request->session()->push('site.xxx', 'Laravel');if($request->session()->has('site')){ $site = $request->session()->get('site'); dd($site);}使用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);更多laravel框架技術文章,請造訪
laravel教學!
以上是session與cookie的機制及laravel框架下的相關應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!