Laravel API verification/protection 在后续请求中:没有登录/注销并且没有 "users" table

Laravel API verification/protection on subsequent requests: no login / logout and no "users" table

TLDR;见下图 3 - 这可能吗?如何实现?


我读到了 API 保护 - Sanctum & Passport,但是其中 none 似乎是我可以用我的应用程序完成的,因为它在某种程度上有点具体和简化。

例如,Sanctum 的身份验证方式听起来像我喜欢的方式,但没有 /login 部分(我有自定义 /auth 部分,见下文。):https://laravel.com/docs/8.x/sanctum#spa-authenticating.

If the login request is successful, you will be authenticated and subsequent requests to your API routes will automatically be authenticated via the session cookie that the Laravel backend issued to your client.

我的应用程序本身没有登录 - 如果用户具有由第 3 方验证的指定 cookie 令牌,我们会登录用户 API(我知道令牌身份验证不是最好的方式,但它非常具体 application/use)。它在 /auth, 上,所以 Sanctum 上面的描述可以工作,我想如果我知道在哪里可以使用它 fiddle。我们的逻辑:

  1. VueJS:移动设备发送加密的 cookie 令牌 - 应用程序在 JS 中读取它,将其发送到我的 Laravel API 进行验证。
  2. 获取LaravelAPI中的token,解密,发送给第二个API(不在我的控制范围内),验证token,发回OK或NOT OK响应有一些数据。
  3. 如果响应正常,则用户“已登录”。
  4. 用户可以在应用程序中导航,并且会出现其他 API 响应 - 我如何验证是他本人而不是冒名顶替者或某人直接在浏览器中访问 API?

我想会话可以解决这个问题,但这是我第一次使用 Laravel,似乎没有任何效果像预期的那样。此外,如果需要,存储在文件或数据库中的会话不是我所期待的。

例如,我尝试在发生上述第3步时设置一个简单的会话参数并将其发回,但会话存储尚未设置,但似乎是在那个时候。然后我可以检查该会话值以确保他是刚刚验证的同一用户。

为了更容易理解我想要完成的事情以及它是否可行:

主要问题是,获得基本 API protection/authentication/verification 的最简单方法是什么,同时仅在 1 日将用于身份验证的令牌发送给第 3 方 API请求(如果应用程序当然是 reopened/refreshed)- 请记住,我的 Laravel API.

上不存在实际用户

或者最好在每个请求上对第 3 方进行令牌验证 API?

如果我对你的情况的理解正确,那么就没有涉及真正的用户模型,对吧?如果是这样,您将无法使用任何 Laravel 的 built-in 身份验证方法,因为它们都依赖于此类模型的存在。

在这种情况下,您需要一个端点和一个自定义身份验证中间件,您需要在 Laravel 中自行创建这些中间件才能处理所有事情:

端点定义:

Route::post('authenticate', [TokenController::class, 'login']);

控制器:

class TokenController extends Controller 
{
    public function login(Request $request)
    {
        // First read the token and decrypt it.
        // Here you'll need to replace "some_decryption()" with the required decrypter based on how your VueJS app encrypts the token.
        $token = some_decryption( $request->input('token') );

        // Then make the request to the verification API, for example using Guzzle.
        $isTokenOk = Http::post('http://your-endpoint.net', [
            'token' => $token,
        ])->successful();

        // Now issue a Laravel API token only if the verification succeeded.
        if (! $isTokenOk) {
            abort(400, 'Verification failed');
        }

        // In order to not store any token in a database, I've chosen something arbitrary and reversibly encrypted.
        return response()->json([
            'api-token' => Crypt::encrypt('authenticated'),
        ]);
    }
}

后续请求应将授权 header 中的 api 令牌作为 Bearer 令牌传递。然后在中间件中,您将检查 Bearer 令牌并检查它是否符合我们的预期值:

class AuthTokenAuthenticationMiddleware
{
    public function handle($request, Closure $next)
    {
        $authToken = $request->bearerToken();

        if (! $authToken || ! Crypt::decrypt($authToken) === 'authenticated') {
            abort(401, 'Unauthenticated');
        }

        return $next($request);
    }
}

中间件需要在app/Http/Kernel.php中注册:

protected $routeMiddleware = [
    ...
    'auth-token' => AuthTokenAuthenticationMiddleware::class,
];

最后将这个新的中间件应用到您应该进行身份验证的任何路由:

Route::middleware('auth-token')->get('some/api/route', SomeController::class);

警告:此身份验证机制依赖于可逆加密。任何能够解密或拥有您的 APP_KEY 的人最终都将能够访问您受保护的端点!

当然,这是处理自定义无用户身份验证的一种方法,还有更多方法。例如,您可以在加密令牌中插入一个到期日期而不是字符串“authenticated”,并验证它是否在中间件中过期。但是您了解了要遵循的步骤的要点...


如果您确实有一个用户模型,那么您可以使用 Laravel Sanctum 并在用户检索后发出 API 令牌,而不是伪造自定义加密令牌。参见 https://laravel.com/docs/8.x/sanctum#issuing-mobile-api-tokens

// Fetch the corresponding user...
$user = User::where('token', $request->input('token'))->first();

return $user->createToken('vuejs_app')->plainTextToken;

后续请求应在授权 header 中将令牌作为 Bearer 令牌传递。

使用Sanctum提供的中间件保护路由:

Route::middleware('auth:sanctum')->get('some/api/route', SomeController::class);