九、高效使用安全性和会话

在本章中,我们将介绍:

  • 加密和解密数据
  • 散列密码和其他数据
  • 在表单中使用 CSRF 令牌和筛选器
  • 在表单中使用高级验证
  • 构建购物车
  • 使用 Redis 保存会话
  • 使用基本会话和 cookies
  • 创建安全的应用编程接口服务器

简介

安全性是我们在构建 web 应用时需要考虑的最重要的事情之一,尤其是当我们处理敏感的用户信息时。Laravel 为我们提供了许多保护应用安全的方法。

在本章中,我们将研究各种方法来屏蔽敏感数据,如何保护我们的表单免受跨站点攻击,以及如何保护应用编程接口。我们还将看到如何使用会话来构建购物车,以及如何使用 Redis 来存储会话数据。

加密和解密数据

在编写处理敏感数据的应用时,我们可能经常想要加密存储在数据库中的任何数据。Laravel 为此提供了一个解决方案。

做好准备

对于这个配方,我们需要一个标准的 Laravel 安装,以及一个正确设置和配置的 MySQL 数据库。

怎么做...

这就是我们如何使用以下步骤完成配方的方法:

  1. app/config目录下,打开app.php文件,确认key为空

    php 'key' => '',

  2. 在命令行中,转到应用的根目录,并使用以下命令生成新密钥:

    php php artisan key:generate

  3. 使用以下命令在数据库中创建一个表来保存我们的敏感信息:

    ```php CREATE TABLE accounts( id int(11) unsigned NOT NULL AUTO_INCREMENT, business varchar(255) DEFAULT NULL, total_revenue varchar(255) DEFAULT NULL, projected_revenue varchar(255) DEFAULT NULL, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    ```

  4. 在我们的app/models目录中,通过输入以下代码创建一个名为Account.php的文件:

    ```php <?php

    class Account extends Eloquent { protected $table = 'accounts'; public $timestamps = false; public function setBusinessAttribute($business) {$this->attributes['business'] = Crypt::encrypt($business); }

    public function setTotalrevenueAttribute($total_revenue) {$this->attributes['total_revenue'] = Crypt::encrypt($total_revenue); }

    public functionsetProjectedrevenueAttribute($projected_revenue) { $this->attributes['projected_revenue'] = Crypt::encrypt($projected_revenue); }

    public function getBusinessAttribute() { return Crypt::decrypt($this->attributes['business']) }

    public function getTotalrevenueAttribute() { return number_format(Crypt::decrypt($this>attributes['total_revenue'])) ; }

    public function getProjectedrevenueAttribute() { return number_format(Crypt::decrypt($this>attributes['projected_revenue'])); } } ```

  5. 在我们的routes.php文件中,通过添加以下代码来创建路线以查看和提交信息:

    ```php Route::get('accounts', function() { $accounts = Account::all(); return View::make('accounts')->with('accounts', $accounts); });

    Route::post('accounts', function() { $account = new Account(); $account->business = Input::get('business'); $account->total_revenue = Input::get('total_revenue'); $account->projected_revenue = Input::get('projected_revenue'); $account->save(); return Redirect::to('accounts'); }); ```

  6. 在我们的views目录中,创建一个名为accounts.php

    php <form action="accounts" method="post"> <label for="business">Business:</label><br> <input name="business"><br><br> <label for="total_revenue">Total Revenue ($):</label><br> <input name="total_revenue"><br><br> <label for="projected_revenue">Projected Revenue($):</label><br> <input name="projected_revenue"><br><br> <input type="submit"> </form> <hr> <?php if ($accounts): ?> <table border="1"> <thead> <tr> <th>Business</th> <th>Total Revenue</th> <th>Projected Revenue</th> </tr> </thead> <tbody> <?php foreach ($accounts as $account): ?> <tr> <td><?= $account->business ?></td> <td>$<?= $account->total_revenue ?></td> <td>$<?= $account->projected_revenue ?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?>

    的文件

它是如何工作的...

我们从移除开始,这是 Laravel 附带的默认键。然后,我们使用artisan命令为我们生成一个新的密钥,它会自动保存在正确的文件中。artisan命令创建了一个相当强的密钥,所以我们不必担心自己想出一个。

为应用创建密钥后,请确保它不会被更改,因为如果您已经使用了一些加密,这会破坏您的应用。

然后我们建立一个数据库表来保存我们的敏感数据。在本例中,我们将存储企业名称及其一些财务数据。

我们的下一步是建立我们的模型,使用Eloquent模型。为了让事情变得简单一点,我们将在模型中使用 getters 和 setters,这样每当在我们的Account模型中设置一个值时,它将使用 Laravel Crypt::encrypt类自动加密。此外,为了从数据库中获取信息,我们的模型会自动为我们解密。

接下来,我们创建几条路线。第一条路线将显示一个添加信息的表单,以及显示数据库中已经保存的任何内容。下一条路线只是采用表单输入,并将其保存到我们的帐户表中的新行。添加信息后,我们将被重定向回帐户列表和表单页面,新数据将显示在页面底部。

然而,如果我们看看数据库本身,我们存储的信息是不可读的文本。这样,如果有人碰巧侵入了我们的数据库,他们就不会得到太多信息。

散列密码和其他数据

当我们将用户密码存储在数据库中时,通常会对其进行散列处理。这有助于防止任何未经授权访问数据库的人看到人们的密码。但是,我们可能还想隐藏用户的电子邮件地址或其他信息,因此没有人能够访问它们。我们可以使用 Laravel 的 Hash 轻松做到这一点。

做好准备

对于这个配方,我们需要一个标准的 Laravel 安装,以及一个正确设置和配置的 MySQL 数据库。

怎么做...

以下是这个食谱的步骤…

  1. 使用以下命令设置数据库表:

    ```php CREATE TABLE register ( id int(10) unsigned NOT NULL AUTO_INCREMENT, username varchar(255) DEFAULT NULL, email char(60) DEFAULT NULL, password char(60) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=1

    ```

  2. views目录中,借助以下代码创建一个名为register.php的文件:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Register</title> </head> <body> <p> <h3>Register</h3> <form method="post" action="register"> <label>User Name</label> <input name="username"><br> <label>Email</label> <input name="email"><br> <label>Password</label> <input name="password"><br> <input type="submit"> </form> </p> <p style="border-top:1px solid #555"> <h3>Login</h3> <form method="post" action="login"> <label>User Name</label> <input name="username"><br> <label>Email</label> <input name="email"><br> <label>Password</label> <input name="password"><br> <input type="submit"> </form> </p> <hr> <table border='1'> <?php if ($users): ?> <tr> <th>User Name</th> <th>Email</th> <th>Password</th> </tr> <?php foreach ($users as $user): ?> <tr> <td><?= $user->username ?></td> <td><?= $user->email ?></td> <td><?= $user->password ?></td> </tr> <?php endforeach; ?> <?php endif; ?> </table> </body> </html>

  3. 在我们的routes.php文件中,通过添加以下代码来创建我们的路线:

    ```php Route::get('register', function() { $users = DB::table('register')->get(); return View::make('register')->with('users', $users); });

    Route::post('register', function() { $data = array( 'username' => Input::get('username'), 'email' => Hash::make(Input::get('email')), 'password' => Hash::make(Input::get('password')));

    DB::table('register')->insert($data);

    return Redirect::to('register'); });

    Route::post('login', function() { $user = DB::table('register')->where('username', '=', Input::get('username'))->first(); if (!is_null($user) and Hash::check(Input::get('email'), $user->email) and Hash::check(Input::get('password'), $user->password)) { echo "Log in successful"; } else { echo "Not able to login"; } });

    ```

它是如何工作的...

为了开始这个方法,我们首先建立一个基本的用户表来保存用户名、电子邮件地址和密码。在这个例子中,用户名是唯一需要在常规文本中的东西。

在我们看来,我们将创建两个表单——一个用于注册,一个用于登录。为了显示数据库中的原始数据,我们还将显示所有用户的列表,以及他们的电子邮件和密码在表中的显示方式。

当我们提交注册表单时,信息会发布到我们的注册路径中,并放入一个数组中。对于电子邮件和密码,我们使用 Laravel 的Hash::make()函数进行散列。然后,我们将数组插入到我们的注册表中,并重定向回表单和列表页面。

重定向后,我们将看到添加了新行,我们的电子邮件和密码被散列,还有一个无法识别的字符串。有趣的是,通过散列的工作方式,我们可以使用完全相同的数据添加两行,散列将完全不同。

接下来,我们可以尝试使用用户名、电子邮件和密码登录。该路由将从我们的表中抓取一行与用户名相对应的内容,然后对输入值和数据库结果运行 Laravel 的Hash::check()函数。如果通过,则返回TRUE,我们可以继续应用。

还有更多...

为了在生产环境中使用这个配方,我们需要对输入进行一些验证。我们可能还想利用雄辩的表单 来让散列变得简单一点。

如果我们不需要隐藏用户的电子邮件,我们也可以使用 Laravel 在Auth::attempt()方法中构建的。更多相关信息可以在拉弗尔网站上找到:http://laravel.com/docs/security#authenticating-users

在表单中使用 CSRF 标记和过滤器

网络表单因黑客试图访问网站或用户信息而臭名昭著。为了让我们的表单更加安全,我们可以使用内置于 Laravel 中的跨站点请求伪造 ( CSRF )策略。这将停止用户会话之外的表单提交。

做好准备

对于这个食谱,我们需要一个标准的安装的 Laravel。

怎么做...

以下是完成该配方的步骤:

  1. routes.php文件中,通过下面给出的代码创建保存和处理表单的路径:

    ```php Route::get('cross-site', function() { return View::make('cross-site'); });

    Route::post('cross-site', array('before' => 'csrf',function() { echo 'Token: ' . Session::token() . '
    '; dd(Input::all()); })); ```

  2. filters.php文件中,确保csrf令牌的filter存在,如以下代码所示:

    php Route::filter('csrf', function() { if (Session::token() != Input::get('_token')) { throw new Illuminate\Session\TokenMismatchException; } });

  3. 在我们的views目录中,创建一个名为cross-site.php的文件,并添加两个表单进行测试,如下代码所示:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>CSRF Login</title> </head> <body> <p> <h3>CSRF Login</h3> <?= Form::open(array('url' => 'cross-site', 'method' =>'post')) ?> <?= Form::token() ?> <?= Form::label('email', 'Email') ?> <?= Form::text('email') ?> <?= Form::label('password', 'Password') ?> <?= Form::password('password') ?> <?= Form::submit('Submit') ?> <?= Form::close() ?> </p> <hr> <p> <h3>CSRF Fake Login</h3> <?= Form::open(array('url' => 'cross-site', 'method' =>'post')) ?> <?= Form::hidden('_token', 'smurftacular') ?> <?= Form::label('email', 'Email') ?> <?= Form::text('email') ?> <?= Form::label('password', 'Password') ?> <?= Form::password('password') ?> <?= Form::submit('Submit') ?> <?= Form::close() ?> </p> </body> </html>

  4. 在浏览器中,转到http://{your-server}/cross-site(其中{your-server}是我们正在使用的服务器的名称),然后提交每个表单以查看结果。

它是如何工作的...

我们的第一步是为我们的 CSRF 形态创建路线。在表单中,我们只需要添加Form::token()功能;这将插入一个名为_token的隐藏字段,以及我们的用户会话 ID 的值。对于提交表单的路线,我们在过滤之前将csrf添加到我们的路线中。如果确定请求是伪造的,页面将返回一个服务器错误。

我们的下一个表单是一个例子,说明如果一个请求试图被伪造会发生什么。对于这个表单,我们不使用Form::token()函数,而是手动添加隐藏字段,并添加一些随机值。然后当我们提交表单时,页面会显示一条带有TokenMismatchException错误的失败消息。

还有更多...

使用Form::open()功能时,Laravel 也会自动生成一个csrf令牌,不需要手动添加。

在表单中使用高级验证

可能有些时候我们需要为验证我们的表单,这不是框架的一部分。这个食谱将告诉你如何建立一个定制的验证规则并应用它。

做好准备

对于这个食谱,我们需要一个标准安装的 Laravel。

怎么做...

以下是完成该配方的步骤:

  1. views目录中,使用以下代码创建一个名为valid.php的文件来保存我们的表单:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Custom Validation</title> </head> <body> <p> <?php if ($errors): ?> <?php echo $errors->first('email') ?> <?php echo $errors->first('captain') ?> <?php endif; ?> </p> <p> <h3>Custom Validation</h3> <?= Form::open(array('url' => 'valid', 'method' => 'post'))?> <?= Form::label('email', 'Email') ?> <?= Form::text('email') ?><br><br> <?= Form::label('captain', 'Your favorite captains (choosethree)') ?><br> <?= 'Pike: ' . Form::checkbox('captain[]', 'Pike') ?><br> <?= 'Kirk: ' . Form::checkbox('captain[]', 'Kirk') ?><br> <?= 'Picard: ' . Form::checkbox('captain[]', 'Picard')?><br> <?= 'Sisko: ' . Form::checkbox('captain[]', 'Sisko') ?><br> <?= 'Janeway: ' . Form::checkbox('captain[]', 'Janeway')?><br> <?= 'Archer: ' . Form::checkbox('captain[]', 'Archer')?><br> <?= 'Crunch: ' . Form::checkbox('captain[]', 'Crunch')?><br> <?= Form::submit('Submit') ?> <?= Form::close() ?> </p> </body> </html>

  2. routes.php文件中,用创建我们的路线,代码如下:

    php Route::get('valid', function() { return View::make('valid'); }); Route::post('valid', function() { $rules = array('email' => 'required|email','captain' => 'required|check_three'); $messages = array('check_three' => 'Thou shalt choose three captains. Nomore. No less. Three shalt be the number thou shaltchoose, and the number of the choosing shall bethree.',); $validation = Validator::make(Input::all(), $rules,$messages); if ($validation->fails()) { return Redirect::to('valid')->withErrors($validation); } echo "Form is valid!"; });

  3. 同样在routes.php文件中,创建我们的自定义验证,如以下代码所示:

    php Validator::extend('check_three', function($attribute,$value, $parameters) { return count($value) == 3; });

它是如何工作的...

首先,我们在视图中创建表单。我们要求一封有效的电子邮件,并且恰好选中三个复选框。由于没有针对三个复选框的 Laravel 验证方法,我们需要创建一个自定义验证。

我们的自定义验证采用输入数组并进行简单的计数。如果达到三,则返回TRUE。如果不是,则返回FALSE,验证失败。

回到我们的表单处理流程,我们需要做的就是将我们创建的自定义验证器的名称添加到我们的验证规则中。如果我们想设置一个自定义消息,我们也可以添加它。

还有更多...

为简单起见,该配方的附加验证程序在routes.php文件中。如果我们有多个自定义验证器,最好将它们放在自己的验证器文件中。为此,我们应该在我们的app目录中创建一个名为validator.php的文件,并添加我们想要的任何代码。然后,在app/start目录中打开global.php文件,并在文件末尾添加require app_path().'/validator.php'功能。这将自动加载我们所有的验证器。

搭建购物车

电子商务是网络上的一项巨大业务。大多数电子商务网站不可或缺的一部分是使用购物车系统。本食谱将介绍如何使用 Laravel 会话来存储待售商品和构建购物车。

做好准备

对于这个食谱,我们需要一个标准的 Laravel 安装,以及一个正确设置和配置的 MySQL 数据库。

怎么做...

要完成此配方,请遵循以下步骤:

  1. 在我们的数据库中,创建一个表,用这个 SQL 代码添加一些数据:

    ```php CREATE TABLE items ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, description text, price int(11) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB;

    INSERT INTO items VALUES ('1', 'Lamp', 'This is a Lamp.','14'); INSERT INTO items VALUES ('2', 'Desk', 'This is a Desk.','75'); INSERT INTO items VALUES ('3', 'Chair', 'This is a Chair.', '22'); INSERT INTO items VALUES ('4', 'Sofa', 'This is a Sofa/Couch.', '144'); INSERT INTO items VALUES ('5', 'TV', 'This is a Television.', '89');

    ```

  2. routes.php文件中,使用以下代码为我们的购物车创建路线:

    ```php Route::get('items', function() { $items = DB::table('items')->get(); return View::make('items')->with('items', $items)>nest('cart', 'cart', array('cart_items' =>Session::get('cart'))); });

    Route::get('item-detail/{id}', function($id) { $item = DB::table('items')->find($id); return View::make('item-detail')->with('item', $item)>nest('cart', 'cart', array('cart_items' =>Session::get('cart'))); });

    Route::get('add-item/{id}', function($id) { $item = DB::table('items')->find($id); $cart = Session::get('cart'); $cart[uniqid()] = array ('id' => $item->id, 'name' => $item >name, 'price' => $item->price); Session::put('cart', $cart); return Redirect::to('items'); });

    Route::get('remove-item/{key}', function($key) { $cart = Session::get('cart'); unset($cart[$key]); Session::put('cart', $cart); return Redirect::to('items'); });

    Route::get('empty-cart', function() { Session::forget('cart'); return Redirect::to('items'); }); ```

  3. views目录下,创建一个名为items.php的文件,代码如下:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Item List</title> </head> <body> <div> <?php foreach ($items as $item): ?> <p> <a href="item-detail/<?= $item->id ?>"> <?= $item->name ?> </a> -- <a href="add-item/<?= $item->id ?>">Add to Cart</a> </p> <?php endforeach; ?> </div> <?php $cart_session = Session::get('cart') ?> <?php if ($cart_session): ?> <?= $cart ?> <?php endif; ?> </body> </html>

  4. views目录中,创建一个名为item-detail.php的文件,其给定代码为:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Item: <?= $item->name ?></title> </head> <body> <div> <h2><?= $item->name ?></h2> <p>Price: <?= $item->price ?></p> <p>Description: <?= $item->description ?></p> <p> <a href="../add-item/<?= $item->id ?>">Add to Cart</a> </p> <p><a href="../items">Item list</a></p> </div> <? if (Session::has('cart')): ?> <?= $cart ?> <? endif; ?> </body> </html>

  5. views目录下,创建一个名为cart.php的文件,代码如下:

    php <div class="cart" style="border: 1px solid #555"> <?php if ($cart_items): ?> <?php $price = 0 ?> <ul> <?php foreach ($cart_items as $cart_item_key =>$cart_item_value): ?> <?php $price += $cart_item_value['price']?> <li> <?= $cart_item_value['name'] ?>: <?= $cart_item_value['price'] ?> (<a href="remove-item/<?= $cart_item_key ?>">remove</a>) </li> <?php endforeach; ?> </ul> <p><strong>Total: </strong> <?= $price ?></p> <?php endif; ?> </div>

  6. 现在,我们可以在浏览器中进入http://{your-server}/items查看数据库中的项目列表、它们详细页面的链接以及将它们添加到购物车中的选项。添加到购物车后,它们将显示在页面底部。

它是如何工作的...

为了开始这个食谱,我们需要建立一个数据库表来保存我们想要添加到购物车中的物品。我们还将添加一些测试项目,因此我们有一些数据可以使用。

在第一条路线中,我们获取表中所有现有的项目并显示它们。我们还嵌套在购物车视图中,该视图将显示我们已经添加的项目。在该嵌套视图中,我们还发送购物车会话,因此列表可以填充。

我们的下一条路线做了类似的事情,但它只接受一个项目,并显示全部信息。

下一条路线实际上添加了这些项目。首先,我们根据项目的标识从数据库中获取项目。然后我们将现有的 cart 会话保存到一个变量中,这样我们就可以操作它了。我们使用 php 的uniqid()函数作为我们的键,将该项目添加到数组中。然后我们将cart阵列放回Session并重定向它。

如果我们想要移除一个物品,我们首先要想办法获取该物品的 ID,并将其从cart数组中移除。另一种方法是删除所有会话并重新开始。

在我们看来,我们还会注意到,我们只允许cart列表显示购物车中是否真的有任何东西。

还有更多...

这个食谱可以很容易地扩展到功能更全。例如,如果我们多次点击同一个项目,我们可以存储每个项目的总数,而不是添加新记录。这样,我们可以在项目旁边添加一个要求数量的表单字段。

使用 Redis 保存会话

Redis 是一个流行的键/值数据存储,速度相当快。Laravel 包括对 Redis 的支持,并使其易于与 Redis 数据交互。

做好准备

对于这个方法,我们需要一个正确配置和运行的 Redis 服务器。更多信息可以在【http://redis.io/】的找到。

怎么做...

按照以下步骤至完成本食谱:

  1. 在我们的routes.php文件中,按照下面的代码创建路线:

    ```php Route::get('redis-login', function() { return View::make('redis-login'); });

    Route::post('redis-login', function() { $redis = Redis::connection(); $redis->hset('user', 'name', Input::get('name')); $redis->hset('user', 'email', Input::get('email')); return Redirect::to('redis-view'); });

    Route::get('redis-view', function() { $redis = Redis::connection(); $name = $redis->hget('user', 'name'); $email = $redis->hget('user', 'email'); echo 'Hello ' . $name . '. Your email is ' . $email; }); ```

  2. views目录下,创建一个名为redis-login.php的文件,代码如下:

    php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Redis Login</title> </head> <body> <p> <h3>Redis Login</h3> <?= Form::open(array('url' => 'redis-login', 'method' =>'post')) ?> <?= Form::label('name', 'Your Name') ?> <?= Form::text('name') ?> <?= Form::label('email', 'Email') ?> <?= Form::text('email') ?> <?= Form::submit('Submit') ?> <?= Form::close() ?> </p> </body> </html>

  3. 现在,我们可以打开浏览器,进入http://{your-server}/redis-login并填写表格。提交后,我们将显示来自 Redis 的信息。

它是如何工作的...

我们的第一步是创建一个简单的表单,我们将使用它向 Redis 输入数据。在我们的redis-login路线中,我们使用一个视图,该视图将询问姓名和电子邮件地址,并且当提交时,将发布到redis-login路线。

发布后,我们使用Redis::connection()函数创建一个新的 Redis 实例,它将使用我们的app/config/database.php文件中的默认设置。为了在 Redis 中存储信息,我们使用了一个散列并使用hset()函数设置数据。我们的 Redis 实例可以使用 Redis 接受的任何命令,因此我们可以很容易地在功能之间进行选择,例如set()sadd()

一旦数据在 Redis 中,我们重定向到将显示数据的路由。为此,我们只需要用我们添加的键和字段调用hget()函数。

使用基本会话和 cookies

有些时候,我们希望将数据从我们应用的一个页面传递到另一个页面,而不需要将信息存储在数据库中。为此,我们可以使用 Laravel 提供的各种SessionCookie方法。

做好准备

对于这个食谱,我们需要一个标准的 Laravel 安装。

怎么做…

对于此配方,请遵循给定的步骤:

  1. views文件夹中,创建一个名为session-one.php的文件,其代码如下:

    php <!DOCTYPE html> <html> <head> <title>Laravel Sessions and Cookies</title> <meta charset="utf-8"> </head> <body> <h2>Laravel Sessions and Cookies</h2> <?= Form::open() ?> <?= Form::label('email', 'Email address: ') ?> <?= Form::text('email') ?> <br> <?= Form::label('name', 'Name: ') ?> <?= Form::text('name') ?> <br> <?= Form::label('city', 'City: ') ?> <?= Form::text('city') ?> <br> <?= Form::submit('Go!') ?> <?= Form::close() ?> </body> </html>

  2. routes.php文件中,按照下面的代码创建我们的路线:

    ```php Route::get('session-one', function() { return View::make('session-one'); });

    Route::post('session-one', function() { Session::put('email', Input::get('email')); Session::flash('name', Input::get('name')); $cookie = Cookie::make('city', Input::get('city'), 30); return Redirect::to('session-two')->withCookie($cookie); });

    Route::get('session-two', function() { $return = 'Your email, from a Session, is 'Session::get('email') . '.
    '; $return .= 'You name, from flash Session, is 'Session::get('name') . '.
    '; $return .= 'You city, from a cookie, is ' .Cookie::get('city') . '.
    '; $return .= 'Next page'; echo $return; });

    Route::get('session-three', function() { $return = '';

    if (Session::has('email')) { $return .= 'Your email, from a Session, is ' . Session::get('email') . '.
    '; } else { $return .= 'Email session is not set.
    '; }

    if (Session::has('name')) { $return .= 'Your name, from a flash Session, is ' . Session::get('name') . '.
    '; } else { $return .= 'Name session is not set.
    '; }

    if (Cookie::has('city')) { $return .= 'Your city, from a cookie, is ' . Cookie::get('city') . '.
    '; } else { $return .= 'City cookie is not set.
    '; } Session::forget('email'); $return .= 'Reload'; echo $return; }); ```

它是如何工作的...

首先,我们创建一个简单的表单,用于向会议和 cookies 提交信息。在发布值后,我们获取email字段并将其添加到常规会话中。name字段将被添加到 flash 会话中,而city将被添加到 cookie 中。此外,我们将设置 cookie 在 30 分钟后过期。一旦它们都设置好了,我们重定向到我们的第二个页面,并确保我们将 cookie 传递给返回值。

我们的第二页只是获取我们设置的值并显示它们,以验证它们是否设置正确。此时,一旦请求完成,我们的闪存会话(名称)将不再可用。

当我们点击进入第三页时,我们添加一些检查以确保会话和 cookies 仍然存在,在这两个页面上使用has()方法。我们的emailcity仍然应该显示,但是name会话不应该显示。然后,我们使用 forget()方法删除email会话。当我们重新加载页面时,我们会注意到唯一还在显示的是city cookie。

还有更多...

闪存数据仅在我们提出下一个请求时可用,然后被删除。但是,如果我们想保留我们的闪存数据,我们可以使用Session::reflash()命令,它也会将数据发送给我们的下一个请求。如果我们有多个闪存数据,我们也可以使用Session::keep(array('your-session-key', 'your-other-session'))功能为下一个请求选择要保留的特定会话。

创建安全的应用编程接口服务器

在这个食谱中,我们将创建一个简单的应用编程接口来显示数据库中的一些信息。为了控制谁有权访问数据,我们允许用户创建密钥,并在他们的 API 请求中使用该密钥。

做好准备

对于这个食谱,我们需要一个标准安装的 Laravel 和一个配置好的 MySQL 数据库。

怎么做...

为了完成这个食谱,我们将遵循以下步骤:

  1. 在我们的数据库中,创建一个表来保存 API 键,如下面的代码所示:

    php CREATE TABLE api ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, api_key varchar(255) DEFAULT NULL, status tinyint(1) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  2. 在数据库中,为一些要访问的示例数据创建一个表,如下面的代码所示:

    ```php CREATE TABLE shows (id int(10) unsigned NOT NULL AUTO_INCREMENT,name varchar(200) NOT NULL,year int(11) NOT NULL,created_at datetime NOT NULL,updated_at datetime NOT NULL,PRIMARY KEY (id)) ENGINE=InnoDB CHARSET=utf8;

    INSERT INTO shows VALUES ('1', 'Happy Days', '1979','2013-01-01 00:00:00', '2013-01-01 00:00:00'); INSERT INTO shows VALUES ('2', 'Seinfeld', '1999', '2013-01-01 00:00:00', '2013-01-01 00:00:00'); INSERT INTO shows VALUES ('3', 'Arrested Development', '2006', '2013-01-01 00:00:00', '2013-01-01 00:00:00'); INSERT INTO shows VALUES ('4', 'Friends', '1997','2013-01-01 00:00:00', '2013-01-01 00:00:00'); ```

  3. models目录下,创建一个名为Api.php

    ```php <?php

    class Api extends Eloquent {

    public $table = 'api'; public $timestamps = FALSE; } ```

    的文件 4. 在models目录中,创建一个名为Show.php

    php <?php class Show extends Eloquent { }

    的文件 5. 在views目录中,创建一个名为api-key.php

    php <!DOCTYPE html> <html> <head> <title>Create an API key</title> <meta charset="utf-8"> </head> <body> <h2>Create an API key</h2> <?php echo Form::open() ?> <?php echo Form::label('name', 'Your Name: ') ?> <?php echo Form::text('name') ?> <br> <?php echo Form::submit('Go!') ?> <?php echo Form::close() ?> </body> </html>

    的文件 6. 在routes.php文件中,创建路线以允许api-key注册

    ```php Route::get('api-key', function() { return View::make('api-key'); });

    Route::post('api-key', function() { $api = new Api(); $api->name = Input::get('name'); $api->api_key = Str::random(16); $api->status = 1; $api->save(); echo 'Your key is: ' . $api->api_key; }); ```

  4. routes.php中,通过以下代码创建路线以进入api:

    php Route::get('api/{api_key}/shows', function($api_key) { $client = Api::where('api_key', '=', $api_key)->where('status', '=', 1)->first(); if ($client) { return Show::all(); } else { return Response::json('Not Authorized', 401); } }); Route::get('api/{api_key}/show/{show_id}', function($api_key, $show_id) { $client = Api::where('api_key', '=', $api_key)->where('status', '=', 1)->first(); if ($client) { if ($show = Show::find($show_id)) { return $show; } else { return Response::json('No Results', 204); } } else { return Response::json('Not Authorized', 401); } });

  5. 要测试出来,在浏览器中,转到http://{your-server}/api-key(其中{your-server}是开发服务器的名称)并填写表格。在下一页,复制生成的密钥。然后,转到http://{your-server}/api/{your-copied-key}/shows,一个节目列表将以json格式出现。

它是如何工作的...

我们从设置我们的桌子和模型开始。我们的 API 表将用于检查密钥,show表将是我们将使用密钥访问的测试数据。

我们的下一个任务是创建一种为我们的应用生成密钥的方法。在这个例子中,我们只取一个名称值。提交后,我们创建一个随机的 16 个字符的字符串作为用户的密钥。然后,我们将信息保存到表中,并向用户显示密钥。

为了使用这个键,我们创建了两条路线来显示信息。第一条路由在 URL 中使用{api_key}通配符,并将该值传递给我们的函数。然后,我们在数据库中查询该键,并确保状态仍然是活动的。这样,如果我们决定撤销用户的密钥,我们可以将状态设置为 false,他们将无法使用该应用编程接口。如果它们不存在或者状态为假,我们用 HTTP 代码 401 来响应,以表明它们没有被授权。否则,我们返回允许我们以json格式显示记录的雄辩对象。

我们的第二条路线将显示一场演出的记录。对于该网址,我们使用{api_key}通配符作为关键字,使用{show_id}通配符作为节目的标识。我们将这些传递给函数,然后像以前一样检查密钥。如果密钥有效,我们确保具有该标识的节目存在,并再次使用“雄辩”对象以json格式仅显示具有给定标识的节目。

还有更多...

我们也可以选择使用 Laravel 过滤器,如果我们更愿意发布 api 密钥。为此,我们将在filters.php文件中创建新的过滤器

Route::filter('api', function()
{
  if ($api_key = Input::get('api_key')) {
  $client = Api::where('api_key', '=', $api_key)->where('status', '=', 1)->first();
  if (!$client) {
  return Response::json('Not Authorized', 401);
}
  } else {
  return Response::json('Not Authorized', 401);
}
});

然后,对于我们的shows路线,我们响应一个发布请求并添加before过滤器,如下代码所示:

Route::post('api/shows', array('before' => 'api', function()
{
  return Show::all();
}));