Laravel 5.x-用于验证PIN的自定义中间件

时间:2019-11-10 00:03:16

标签: laravel laravel-5 eloquent

我已经阅读了Laravel的中间件文档,但是我感觉有些误会。

我想做的只是在每次查看图书之前进行身份验证。

例如如果我转到'\ book \ funnybook'redirect =>'\ book \ funnybook \ authenticate'(表示输入PIN码)

我遇到的问题是:

  • 我不知道在哪里放置重定向功能(中间件?控制器?)
  • 我不知道从何处检索用户输入的值并将其与数据库值进行比较。再说一遍我应该放在哪里?在中间件或控制器中?我的视图将如何调用该函数?

2 个答案:

答案 0 :(得分:0)

在Controller中进行身份验证的后功能。类似下图

public function postPin(Request $request){
    ...
    ...


    return Redirect::intended();
}

答案 1 :(得分:0)

让我们创建此类中间件的最小示例,以便您可以在那里进行改进。

根据您的解释,我认为每本书都会有自己的图钉。如果您需要其他功能,可以更改该行为。

首先,让我们创建用于查看/验证图书的路线:

routes/web.php

use Illuminate\Support\Facades\Route;

Route::group(['prefix' => 'book'], function () {
  // view authenticated book
  Route::get('{bookSlug}', 'BookController@view')->name('book.view');
  // show book authenticate form
  Route::get('{bookSlug}/authenticate', 'BookController@showAuth')->name('book.authenticate');
  // handle user input, authenticate book
  Route::post('{bookSlug}/authenticate', 'BookController@authenticate');
});

我们还为bookSlug参数添加模式(如图所示更新boot方法):

app/Providers/RouteServiceProvider.php

class RouteServiceProvider extends ServiceProvider {
  // ...
  public function boot()
  {
    Route::pattern('bookSlug', '[A-Za-z0-9_-]+');
    parent::boot();
  }
  // ...
}

现在,让我们创建中间件:

php artisan make:middleware CheckPin

每个中间件都具有handle方法,该方法允许其检查某些内容并允许请求通过下一步(通过调用$next()闭包),或者通过抛出错误或重定向到另一个URL来停止请求处理

在这里,我们将在会话中检查图书身份验证状态。它将通过身份验证表单存储在此处。如果图书尚未通过身份验证,我们将重定向到身份验证表单。

app/Http/Middleware/CheckPin.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Route;

class CheckPin {

  public function handle($request, Closure $next)
  {
    $bookSlug = Route::current()->parameter('bookSlug');
    // check whether book has been authenticated
    // redirect to auth form otherwise
    if(!session("books.$bookSlug")) {
      return redirect()->route('book.authenticate', compact('bookSlug'));
    }
    return $next($request);
  }
}

我们必须在Kernel.php中注册我们的中间件(如图所示进行更新):

app/Http/Kernel.php

use App\Http\Middleware\CheckPin;
//...

class Kernel extends HttpKernel {
  //...
    protected $routeMiddleware = [
      //...
      'pin' => CheckPin::class, //
    ];

    protected $middlewarePriority = [
      //...
      CheckPin::class,
    ];

  //...
}

让我们创建简单的视图。创建resources/views/book文件夹并在其中放置视图。

用于显示图书内容的视图:
resources/views/book/view.blade.php

<h1>View book &rarr; {{ $bookSlug }}</h1>
<p>Some content</p>

查看图书展示授权表:
resources/views/book/auth.blade.php

<h1>Authenticate &rarr; {{ $bookSlug }}</h1>
<form method="post" action="{{ route('book.authenticate', compact('bookSlug')) }}">
  @csrf
  <label for="pin">Enter pin:</label>
  <input type="password" name="pin" id="pin" required autofocus />
  <button class="submit">Authenticate</button>
  @error('pin')
  <p>
    <i><b>Error:</b> {{ $message }}</i>
  </p>
  @enderror
</form>

最后,让我们创建一个书籍控制器,该控制器将显示书籍,身份验证表单并处理用户输入。

php artisan make:controller BookController

app/Http/Controllers/BookController.php

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class BookController extends Controller {

  public function __construct()
  {
    // "pin" middleware will protect all methods except @showAuth and @authenticate
    $this->middleware('pin')->except(['showAuth', 'authenticate']);
  }

  function view(Request $request, string $bookSlug)
  {
    return view('book.view', compact('bookSlug'));
  }

  function showAuth(Request $request, string $bookSlug)
  {
    return view('book.auth', compact('bookSlug'));
  }

  // handles user input, checks for valid pin
  // redirects to the authenticated book or back to the form
  function authenticate(Request $request, string $bookSlug)
  {
    $pin = $request->input('pin');
    // Check book pin here; for testing purpose: pin should equal book slug
    if($pin === $bookSlug) {
      session()->put("books.$bookSlug", 1);
      return redirect()->route('book.view', compact('bookSlug'));
    }
    return redirect()->back()->withErrors(['pin' => ['Invalid pin']]);
  }
}

它是这样的:
当用户打开某本书时,例如book/funny,它将被重定向到book/funny/authenticate,他们可以在其中输入图钉并验证该书。如果该图钉有效,则将用户重定向回book/funny URL,否则显示错误。


仅此而已。您可以扩展此示例,使其更适合您的需求:向BookController添加更多方法,从数据库中检查书钉等。