HTTP层 —— Session
?
1、簡介
由于HTTP驅動的應用是無狀態的,所以我們使用來存儲用戶請求信息。通過干凈、統一的API處理后端各種Session驅動,目前支持的流行后端驅動包括、和。
配置
Session配置文件位于config/session.php。默認情況下,Laravel使用的session驅動為文件驅動,這對許多應用而言是沒有什么問題的。在生產環境中,你可能考慮使用memcached或者redis驅動以便獲取更快的session性能。
session驅動定義請求的Session數據存放在哪里,Laravel可以處理多種類型的驅動:
file – session數據存儲在 storage/framework/sessions目錄下; cookie – session數據存儲在經過加密的安全的cookie中; database – session數據存儲在數據庫中 memcached / redis – session數據存儲在memcached/redis中; array – session數據存儲在簡單PHP數組中,在多個請求之間是非持久化的。注意:數組驅動通常用于運行測試以避免session數據持久化。
Session驅動預備知識
數據庫
當使用databasesession驅動時,需要設置表包含session項,下面是該數據表的表結構聲明:
Schema::create('sessions', function ($table) {$table->string('id')->unique();$table->integer('user_id')->nullable();$table->string('ip_address', 45)->nullable();$table->text('user_agent')->nullable();$table->text('payload');$table->integer('last_activity'); });你可以使用Artisan命令session:table來生成遷移:
php artisan session:table php artisan migrateRedis
在Laravel中使用Redis作為 session驅動前,需要通過Composer安裝predis/predis包??梢栽赿atabase配置文件中配置Redis連接,在session配置文件中,database選項用于指定session使用哪一個redis連接。
2、使用Session
獲取數據
在Laravel中主要有兩種方式處理Session數據:全局的輔助函數session,或者通過Request實例。首先,我們通過Request實例來訪問Session數據,可以在控制器方法中通過類型提示引入該實例,記住,控制器方法依賴通過Laravel自動注入:
<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request; use App\Http\Controllers\Controller;class UserController extends Controller{/*** 顯示指定用戶的屬性** @param Request $request* @param int $id* @return Response*/public function showProfile(Request $request, $id){$value = $request->session()->get('key');//} }從session中獲取數據的時候,還可以傳遞默認值作為第二個參數到get方法,默認值在指定鍵在session中不存在時返回。如果你傳遞一個閉包作為默認值到get方法,該閉包會執行并返回執行結果:
$value = $request->session()->get('key', 'default');$value = $request->session()->get('key', function() {return 'default'; });全局輔助函數session
還可以使用全局的PHP函數session來獲取和存儲session中的數據,如果只傳遞一個字符串參數到session方法,則返回該session key對應的值;如果傳遞的參數是key/value鍵值對數組,則將這些數據保存到session:
Route::get('home', function () {// 從session中獲取數據...$value = session('key');// 指定默認值...$value = session('key', 'default');// 存儲數據到session...session(['key' => 'value']); });注:通過HTTP請求實例和輔助函數session處理數據并無實質性差別,這兩個方法在測試用例中都可以通過assertSessionHas方法進行測試。
獲取所有Session值
如果你想要從session中獲取所有數據,可以使用all方法:
$data = $request->session()->all();判斷session中是否存在指定項
has方法可用于檢查數據項在session中是否存在。如果存在并且不為null的話返回true:
if ($request->session()->has('users')) {// }要判斷某個值在session中是否存在,即使是null的話也無所謂,則可以使用exists方法。如果值存在的話exists返回true:
if ($request->session()->exists('users')) {// }存儲數據
獲取到session實例后,就可以調用多個方法來與底層數據進行交互,例如,put方法存儲新的數據到session中:
//通過put方法 $request->session()->put('key', 'value');//通過全局輔助函數 session(['key' => 'value']);推送數據到數組session
push 方法可用于推送數據到值為數組的session,例如,如果user.teams鍵包含團隊名數組,可以像這樣推送新值到該數組:
$request->session()->push('user.teams', 'developers');獲取并刪除數據
pull方法將會從session獲取并刪除數據:
$value = $request->session()->pull('key', 'default');一次性數據
有時候你可能想要在session中存儲只在下個請求中有效的數據,可以通過flash方法來實現。使用該方法存儲的session數據只在隨后的HTTP請求中有效,然后將會被刪除:
$request->session()->flash('status', 'Task was successful!');如果你需要在更多請求中保持該一次性數據,可以使用reflash方法,該方法將所有一次性數據保留到下一個請求,如果你只是想要保存特定一次性數據,可以使用keep方法:
$request->session()->reflash(); $request->session()->keep(['username', 'email']);刪除數據
forget方法從session中移除指定數據,如果你想要從session中移除所有數據,可以使用flush方法:
$request->session()->forget('key'); $request->session()->flush();重新生成Session ID
重新生成Session ID經常用于阻止惡意用戶對應用進行session fixation攻擊(關于session fixation 攻擊可參考這篇文章:)。
如果你使用內置的LoginController的話,Laravel會在認證期間自動重新生成session id,如果你需要手動重新生成session ID,可以使用regenerate方法:
$request->session()->regenerate();3、添加Session驅動
實現驅動
自定義session驅動需要實現SessionHandlerInterface接口,該接口包含少許我們需要實現的方法,比如一個MongoDB的實現如下:
<?phpnamespace App\Extensions;class MongoHandler implements SessionHandlerInterface {public function open($savePath, $sessionName) {}public function close() {}public function read($sessionId) {}public function write($sessionId, $data) {}public function destroy($sessionId) {}public function gc($lifetime) {} }注:Laravel默認并沒有附帶一個用于包含的目錄,你可以將擴展放置在任何地方,這里我們創建一個Extensions目錄用于存放MongoHandler。
由于這些方法并不是很容易理解,所以我們接下來快速過一遍每一個方法:
open 方法用于基于文件的session存儲系統,由于Laravel已經有了一個 file session 驅動,所以在該方法中不需要放置任何代碼,可以將其置為空方法。 close 方法和open 方法一樣,也可以被忽略,對大多數驅動而言都用不到該方法。 read 方法應該返回與給定$sessionId 相匹配的session數據的字符串版本,從驅動中獲取或存儲session數據不需要做任何序列化或其它編碼,因為Laravel已經為我們做了序列化。 write 方法應該講給定$data 寫到持久化存儲系統相應的$sessionId , 例如MongoDB, Dynamo等等。 destroy 方法從持久化存儲中移除 $sessionId 對應的數據。 gc 方法銷毀大于給定$lifetime 的所有 session數據,對本身擁有過期機制的系統如 Memcached 和Redis而言,該方法可以留空。注冊驅動
驅動被實現后,需要準備將其注冊到框架,要添加額外驅動到Laravel session后端,可以使用Session門面上的extend方法。我們在的boot方法中調用該方法:
<?phpnamespace App\Providers;use App\Extensions\MongoSessionStore; use Illuminate\Support\Facades\Session; use Illuminate\Support\ServiceProvider;class SessionServiceProvider extends ServiceProvider {/*** Perform post-registration booting of services.** @return void*/public function boot(){Session::extend('mongo', function($app) {// Return implementation of SessionHandlerInterface...return new MongoSessionStore;});}/*** Register bindings in the container.** @return void*/public function register(){//} }session驅動被注冊之后,就可以在配置文件config/session.php中使用mongo 驅動了。
轉載于:https://www.cnblogs.com/zhengyanbin2016/p/6005075.html
總結
以上是生活随笔為你收集整理的HTTP层 —— Session的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: angular2 组件之间通讯-使用服务
- 下一篇: DataTable添加列和行的三种方法