Laravel Vue SPA登录

时间:2019-05-26 16:55:02

标签: laravel vue.js login

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

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

2 个答案:

答案 0 :(得分:0)

听起来不安全,不:)

我从没使用过Laravel,所以我不能专门谈论它,但是我可以解释该过程是如何工作的。

在服务器中,您应该具有中间人或某种逻辑,可以读取令牌并验证其完整性。令牌本身只是具有三个组成部分的Base64字符串

  1. 标题
  2. 有效负载(实际数据)
  3. 签名

如果您有令牌,那么它很容易读取有效负载,因为它只是Base64字符串。因此,仅阅读它还不够,您需要确保签名正确。

创建JWT令牌时,当服务器发出请求时,会秘密进行。服务器应验证签名,以确保这是一个有效的令牌。如果您没有机密,则无法验证签名。只有你应该拥有秘密。

这将阻止“我作为攻击者”发送带有伪造有效载荷的令牌。通过验证签名,您可以确保这是您创建的令牌,而不是我发送给您的网站的伪造令牌。

您也不应该将该令牌存储在本地存储中。本地存储绝不应该包含令牌或密码之类的信息,因为这只是每个人都可以访问的字典/地图。因此,我可以创建一个读取本地存储的网站,获取您创建的令牌,并且由于这是带有正确签名的令牌,因此我现在可以向您的网站发出请求。

我建议将JWT令牌存储在https上的httpOnly cookie中(安全:大多数环境下为true选项)。浏览器无法读取httpOnly cookie,只能读取服务器。

从VueJS应用向服务器发出请求时,例如保存服务器上的博客帖子

  1. 永远不要盲目相信JWT中的有效载荷。
  2. 从不信任VueJS应用程序中的用户信息。
  3. 始终在服务器端验证用户(通过验证示例中令牌的签名)

例如

methods: {
  saveBlogPost() {
    axios.post('/api/save', {
      title: 'My blog title'
      userId: 'bergur'
    })
  }
}

您的服务器永远不要读取从VueJS应用发送的userId。 JWT中间人应该检查JWT,验证其完整性,然后使用有效负载中的信息。

编辑:我回答了一篇有关保护VueJS应用程序安全的类似文章。您可以在这里找到它:VueJS Secure with Auth0 - How is it secure?

基本上:可以在客户端中存储有助于使用户界面有意义的信息,但是在进行实际工作(例如保存到数据库或获取某些私有数据)时,服务器应始终验证用户身份。

答案 1 :(得分:0)

保护服务器端路由很重要。我为此使用的解决方案是使用lcobucci/jwt中的php jwt库Laravel

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

无论您使用哪种框架进行JWT身份验证的步骤都是相同的:

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

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

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

对于这些步骤,创建一个JWT_SECRET env变量。这将是一个很大的随机字符串。您可以使用任何random string generator for this。例如:

JWT_SECRET=bX7fsuHzOksB27Pwh31qmazMsalw4bchu7Ft1X4PMOhO23Zq8nwBKA0FZQOK

创建api sign-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 docslcobucci/jwt,以更好地理解步骤以及如何使用内置的jwt claimsLaravel工具来获得安全良好的解决方案。< / p>

相关问题