教程 > laravel 教程 > 阅读:40

http session——迹忆客-ag捕鱼王app官网

简介

由于支持http协议的应用程序是无状态的,因此laravel session提供了一种在多个请求中存储相关用户信息的方法。laravel附带了各种会话后端,它们可以通过一个表现性的统一api进行访问。像对流行的数据库或缓存的支持

配置

session配置文件存储在config/session.php。确保此文件中的选项可用。默认情况下,laravel配置为使用file 存储session,这可以很好地工作。

session driver配置选项定义了每个请求的会话数据将存储在何处。laravel支持一些出色的驱动程序:

  • file-会话存储在storage/framework/sessions中。
  • cookie -会话存储在安全的加密cookie中。
  • database -会话存储在关系数据库中。
  • memcached/ redis-会话存储在这些快速,基于缓存的应用之一。
  • array -会话存储在php数组中,但是不会持久保存。

数组驱动程序在测试期间使用,可防止持久存储在会话中的数据。

驱动程序先决条件

数据库

使用database会话驱动程序时,我们将需要创建一个包含会话项的表。下面是使用schema创建表的示例:

schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->foreignid('user_id')->nullable();
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity');
});

我们可以使用artisan命令session:tableartisan命令快速生成:

$ php artisan session:table
$ php artisan migrate

redis

在laravel使用redis会话之前,我们需要通过pecl安装phpredis php扩展或通过composer安装predis/predis package(〜1.0 )。有关配置redis的更多信息,请参阅其 laravel redis文档 页面。


使用session

检索数据

在laravel中使用会话数据主要有两种方法:

  • 全局session帮助函数
  • 通过request实例

首先,让我们看一下通过request实例访问会话的情况,该实例可以在控制器方法中使用类型限定。请记住,控制器方法依赖项是通过laravel 服务容器自动注入的:

session()->get('key');
        //
    }
}

检索会话中数据时,我们还可以给get方法传递第二个参数作为默认值。如果会话中不存在指定的key的值,则将返回此默认值。如果给get方法的第二个参数传一个closure,并且请求的键不存在,closure则将执行并返回其结果:

$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
    return 'default';
});

全局session 帮助函数

我们可以使用全局session 函数在会话中检索和存储数据。当session帮助函数只有一个字符串参数时,它将返回会话中该key的值。当session函数的参数是一个键/值对数组时,这些值将存储在会话中:

route::get('home', function () {
    // retrieve a piece of data from the session...
    $value = session('key');
    // specifying a default value...
    $value = session('key', 'default');
    // store a piece of data in the session...
    session(['key' => 'value']);
});

通过http request实例使用session与使用全局session帮助函数之间几乎没有实际区别。两种方法都可以在任何的测试用例中使用assertsessionhas方法进行测试。

检索所有session数据

如果要检索session中的所有数据,可以使用all方法:

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

确定会话中是否存在项目

要确定会话中是否存在某项,可以使用has方法。如果存在,并且其值不是null,则has方法返回true:

if ($request->session()->has('users')) {
    //
}

has方法是有缺陷的,对于值为null的项是不能检测出来的。这种情况,我们可以使用exists方法。如果存在该项目,即使其值为null,exists方法也会返回true:

if ($request->session()->exists('users')) {
    //
}

存储数据

要在会话中存储数据,通常使用put方法或session帮助函数:

// via a request instance...
$request->session()->put('key', 'value');
// via the global helper...
session(['key' => 'value']);

将数组作为session值

如果session值是一个数组,可以使用push方法给该数组加入新的值。例如,如果user.teams是一个包含team名称的数组,则可以像这样将新值推送到该数组:

$request->session()->push('user.teams', 'developers');

检索和删除项目

pull方法将在单个语句中检索并删除会话中的项目:

$value = $request->session()->pull('key', 'default');

闪存数据

有时我们可能希望在session中存储数据,仅为下一个请求可以使用。我们可以使用flash方法进行此操作。使用此方法存储在会话中的数据是立即可用的,并且仅在下一个http请求期间可用。在下一个http请求之后,该数据将被删除。flash数据主要用于短暂的状态消息:

$request->session()->flash('status', 'task was successful!');

如果需要为几个请求保留flash数据,则可以使用reflash方法,该方法将保留所有flash数据以供其他请求使用。如果只需要保留特定的闪存数据,则可以使用keep方法:

$request->session()->reflash();
$request->session()->keep(['username', 'email']);

删除数据

forget方法将从会话中删除一条数据。如果要从会话中删除所有数据,可以使用flush方法:

// forget a single key...
$request->session()->forget('key');
// forget multiple keys...
$request->session()->forget(['key1', 'key2']);
$request->session()->flush();

重新生成会话id

为了防止恶意用户利用应用程序上的会话固定攻击,通常我们会重新生成会话id

如果使用内置方法logincontroller,laravel会在身份验证过程中自动重新生成会话id 。但是,如果需要手动重新生成会话id,则可以使用regenerate方法。

$request->session()->regenerate();

会话阻塞

默认情况下,laravel允许在并发请求中使用同一个会话。因此,例如,如果我们使用javascript http库向应用程序发出两个http请求,则它们将同时执行。对于许多应用程序来说,这不是问题。但是,会话数据丢失可能会在一小部分应用程序中发生,这些应用程序会同时向两个不同的应用程序端点发出并发请求,而这两个端点均会将数据写入会话。

为了避免这种情况,laravel会限制对一个会话的并发请求数量。首先,我们可以简单地将block方法加到相应的路由上。在下面示例中,到/profile端点的传入请求将获取会话锁。在锁定期间,对/profile/order共享相同会话id的任何传入请求将等待第一个请求完成执行,然后再继续执行:

route::post('/profile', function () {
    //
})->block($lockseconds = 10, $waitseconds = 10)
route::post('/order', function () {
    //
})->block($lockseconds = 10, $waitseconds = 10)

block方法接受两个可选参数。block方法接受的第一个参数是会话锁在释放之前应保持的最大秒数。当然,如果请求在此时间之前完成执行,则锁将提前释放。

block方法接受的第二个参数是请求尝试获得会话锁时应等待的秒数。如果请求无法在给定的秒数内获得会话锁,则将会抛出一个illuminate\contracts\cache\locktimeoutexception异常。

如果没有传递这些参数,则将最多获得10秒的锁定,而等待时间10秒:

route::post('/profile', function () {
    //
})->block()

添加自定义会话驱动程序

实现驱动程序

我们的自定义会话驱动程序应实现sessionhandlerinterface 接口。该接口仅包含一些我们需要实现的简单方法。一个简单的mongodb实现看起来像这样:

laravel没有附带包含 extensions 的目录。我们可以随意将它们放置在喜欢的任何位置。在此示例中,我们创建了一个extensions目录来存放mongosessionhandler

由于这些方法不容易理解,下面我们快速介绍这些方法的作用:

  • open方法通常将在基于文件的会话存储系统中使用。由于laravel附带了file会话驱动程序,因此我们几乎不需要在此方法中放入任何内容。您可以将其保留为空存根。接口设计不佳(我们将在后面讨论),php要求我们实现该接口的所有方法。
  • close方法与open方法一样,通常也可以忽略该方法。对于大多数驱动程序,不需要它。
  • read方法应返回与给定$sessionid关联的会话数据的版本,该版本是一个字符串。在驱动程序中检索或存储会话数据时,无需进行任何序列化或其他编码,因为laravel会为我们执行序列化。
  • write方法应将与给定$sessionid 关联的数据$data存储到某些持久性存储系统,例如mongodb,dynamo等。同样,我们不应该执行任何序列化-laravel已经为我们进行了序列化。
  • destroy方法应从该$sessionid的持久性存储中删除与之关联的数据。
  • gc方法应销毁所有超过给定时间$lifetime(unix时间戳)的会话数据。对于像memcached和redis这样的系统(存储到其中的数据本身就有到期时间),此方法可以保留为空。

注册驱动程序

一旦实现了驱动程序,就可以在框架中注册它了。要将其他驱动程序添加到laravel的会话后端,可以使用session facade上的extend方法。我们应该从service provider的boot方法中调用该方法。我们可以从现有的 appserviceprovider 中创建,也可以创建一个全新的provider:

一旦注册了会话驱动程序,就可以在config/session.php配置文件中使用该mongo驱动程序。

查看笔记

扫码一下
查看教程更方便
网站地图