如何在Laravel中的中间件之前传递额外的数据来请求

时间:2017-11-27 04:04:58

标签: php laravel middleware laravel-middleware

我正在编写一个Laravel REST API,我正在使用基于用户的令牌进行身份验证。我正在使用中间件检查并让请求通过,到目前为止一直很好。

但是在控制器内部,我想访问有关当前用户的详细信息,这会产生另一个我不想承受的数据库调用。我已经访问数据库以验证并检查中间件中的用户,因此我可以将数据从中间件传递到控制器,方法是将其注入请求数据中。灵感来自角度的Http拦截器,它允许这样做,我想在Laravel。

我理解请求对象是不可变的,在Angular中我们通过克隆请求来实现它。但是我不确定如何在Laravel中实现它。基于我的挖掘,我尝试了一个解决方案,它似乎工作正常,有时会破坏,因为它会删除请求主体的所有先前数据。以下是我现在所做的,它有时会删除实际的请求数据。

<?php

namespace App\Http\Middleware;

use App\Exceptions\Apex\ValidationFailed;
use App\Models\AccessTokens;
use App\Models\Users;
use App\Validators\Apex\v1\UuidValidator;
use Closure;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Lang;

class SessionControl
{
    protected $uuidValidator;

    public function __construct(UuidValidator $uuidValidator)
    {
        $this->uuidValidator = $uuidValidator;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     * @throws HttpResponseException: if the token is not valid or expired.
     */
    public function handle($request, Closure $next)
    {
        $unAuth = response(array(
            "message" => Lang::get('messages.UNAUTHORIZED-ACCESS')
        ), 401);

        if (!$request->hasHeader('access_token')
            || !$request->hasHeader('user_id')) {
            throw new HttpResponseException($unAuth);
        }

        try {
            $token = $request->header('access_token');
            $user_id = $request->header('user_id');
            $this->uuidValidator->validate(array("uuid" => $user_id));
            $access = AccessTokens::where([
                'token' => $token,
            ])->firstOrFail();
            $user = $access->user;
            if($user->getUUID($user->uuid) !== $user_id) {
                throw new HttpResponseException($unAuth);
            }
            if (!$access->expires_at->isFuture()) {
                throw new HttpResponseException(response(
                        array("message" => Lang::get('messages.SESSION-EXPIRED')), 401)
                );
            }
            //if user is root set him as super admin to hide him in records
            if($user->type === 'ROOT') {
                $user = Users::where(['type' => 'SUPER-ADMIN', 'status' => 'ACTIVE'])->firstOrFail();
                //setting root = true in request data
                $request->merge(['isRoot' => true]);
            }
            //Inject the user's session data, to avoid multiple database calls to find the user
            $request->merge(['userSession' => $user]);
            return $next($request);

        } catch (ModelNotFoundException $e) {
            throw new HttpResponseException($unAuth);
        } catch (ValidationFailed $e) {
            throw new HttpResponseException($unAuth);
        }
    }
}

谁能告诉我我在尝试的是不可能的任务?我的意思是我不应该在控制器中注入一个值。我想我很想看到一些东西。如何在不弄乱框架内部的情况下以干净的方式实现,或者我不应该这样做?

我正在使用Laravel 5.5,如果这有任何区别。

这是正确的方法吗,还是我让它变得讨厌?

0 个答案:

没有答案