首页 > 解决方案 > Laravel Vue SPA 登录

问题描述

我刚刚创建了 Vue + Laravel SPA 登录,但我不确定它是否足够安全。我是 VUE 的新手 :)

我正在使用 JWT 身份验证。当用户输入凭据并提交表单时,Laravel 端的 Auth 返回带有令牌的用户模型。此用户存储在本地存储中。在我的 Vue 路由器中,我创建了在每次视图更改之前运行的中间件。这很好用,但数据库中没有与该用户相关的实际令牌。当我手动更改存储中的令牌时,我仍在传递中间件,因为不再检查令牌。它只是检查本地存储中是否存在......我应该将令牌存储在数据库中并在每次视图更改时检查它吗?或者...??

标签: laravelvue.jslogin

解决方案


保护您的服务器端路由很重要。我为此使用的解决方案是使用 .php 中的 php jwtlcobucci/jwtLaravel

我将解释使用默认且更简单的方法 JWT 秘密策略,而不是私钥/公钥策略(如 RSA)。

无论您使用什么框架进行JWT身份验证,步骤都将始终相同:

  1. 用户登录。
  2. 用户凭据(电子邮件/用户名和密码)作为发布请求从您的客户端(vue)发送到您的服务器端(Laravel)
  3. 在服务器端验证凭据是否正确
  4. 如果正确,请使用 jwt 密钥为该用户签署 JWT 令牌。
  5. 将创建的 jwt 令牌作为响应发送给客户端。
  6. 将 JWT 令牌存储在 localStorage 中,并将其添加到标头以供将来请求。

一个简单的服务器端实现将包括

  1. 创建jwt secret环境变量
  2. 创建登录路径
  3. 为传入请求创建中间件以验证令牌

对于这些步骤,创建一个JWT_SECRET环境变量。这将是一个很大的随机字符串。您可以为此使用任何随机字符串生成器。例子:

JWT_SECRET=bX7fsuHzOksB27Pwh31qmazMsalw4bchu7Ft1X4PMOhO23Zq8nwBKA0FZQOK

创建 apisign-in路由 Route::post('authenticate', 'AuthenticateController@signIn');

app/Http/Controllers/AuthenticateController.php

<?php 

namespace App\Http\Controllers;

use App\Services\JWTService;

class AuthenticateController extends Controller
{

    protected $jwt;

    public function __construct(JWTService $jwt)
    {
        $this->jwt = $jwt;
    }

    public function signIn(Request $request){
        $token = $this->jwt->createToken();
        $response = response()->json([  
            'message' => StatusCode::$texts[StatusCode::HTTP_OK],
            'data' => [ 'token' => (string)$token]
        ], StatusCode::HTTP_OK);

        return $response;

    }
}

app/Services/JWTService.php

<?php 
namespace App\Services;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Token;

class JWTService
{
    public function createToken($privilege = 'externalUser'){
        // eval(\Psy\sh());

        $signer = new Sha256();
        $key = new Key(env('JWT_SECRET')); // vindo null
        $time = time();
        $token = (new Builder())->issuedBy($privilege)->expiresAt($time + 3600)->getToken($signer, $key);
        //->withClaim('uid', 1) // Configures a new claim, called "uid"

        return $token;
    }

    public function parseString($bearerToken) : Token {
        return (new Parser())->parse($bearerToken);
    }

    public function verify($token){
        $signer = new Sha256();
        $key = new Key(env('JWT_SECRET'));
        if(!$token->verify($signer, $key))
            abort(401, 'Unauthorized access.');

        return true;
    }

}

为了保护您的路由,请为所有传入请求(登录除外)添加一个中间件。使用 jwt 声明的授权逻辑将由您自己制作。

<?php

namespace App\Http\Middleware;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use OutOfBoundsException;
use BadMethodCallException;

use Closure;

class Authorization
{

    public function handle($request, Closure $next)
    {

        try {

            $bearerToken = $request->bearerToken();

            if(!isset($bearerToken))
                abort(401, 'Unauthorized access.');

            $token = (new Parser())->parse($bearerToken); // Parses from a string
            $signer = new Sha256();
            $key = new Key(env('JWT_SECRET'));
            if(!$token->verify($signer, $key))
                abort(401, 'Unauthorized access.');
            return $next($request);

        } catch(OutOfBoundsException $e){
            abort(401, 'Requested data is not configured.');
        } catch(BadMethodCallException $e){
            abort(403, 'Token not signed.');
        }

    }
    // $token->getHeaders(); // Retrieves the token header
    // $token->getClaims(); // Retrieves the token claims
    // $token->getClaim('iss');
    // $token->getClaim('exp');
}

将中间件添加到kernel.php

protected $routeMiddleware = [
    ...
    'tokenAuth' => \App\Http\Middleware\Authorization::class
];

这样您就可以通过routes/api.php这种方式添加中间件:

 Route::group(['middleware' => 'tokenAuth'], function(){
        Route::resource('user', 'UserController');
        Route::resource('Foo', 'FooController');
 }

我强烈建议阅读Laravel 文档lcobucci/jwt以更好地理解这些步骤以及如何使用jwt claimsLaravel内置工具实现安全和良好的解决方案。


推荐阅读