首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Laravel Vue SPA登录

Laravel Vue SPA登录
EN

Stack Overflow用户
提问于 2019-05-27 00:55:02
回答 2查看 1.2K关注 0票数 1

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

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

EN

回答 2

Stack Overflow用户

发布于 2019-05-27 02:03:53

听起来不像是安全的,不:)

我从来没有使用过Laravel,所以我不能具体讨论它,但我可以解释这个过程是如何工作的。

在你的服务器中,你应该有一个中间件或者某种逻辑来读取令牌并验证它的完整性。令牌本身只是一个包含三个组件的Base64字符串

  1. Header
  2. Payload (实际的data)
  3. Signature

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

当您创建一个JWT令牌时,当您的服务器有一个请求时,您可以使用一个秘密来执行此操作。服务器应验证签名以确保这是有效的令牌。如果你没有这个秘密,你就不能验证签名。只有你才应该知道这个秘密。

这会阻止“我作为攻击者”发送带有虚假负载的令牌。通过验证签名,您可以确保这是您创建的令牌,而不是我发送到您网站的某个假令牌。

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

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

当从VueJS应用程序向服务器发出请求时,比如保存博客文章,服务器应该

  1. 从不信任JWT blindly.
  2. Never中的有效负载信任来自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?

基本上:将信息存储在客户端是很好的,这有助于使用户界面变得有意义,但在执行实际工作时,如保存到数据库中或获取一些私有数据,服务器应该始终验证用户。

票数 0
EN

Stack Overflow用户

发布于 2020-06-12 00:43:01

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

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

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

  1. 用户登录。作为post请求从客户端(Vue)向服务器发送
  2. 用户凭据(电子邮件/用户名和密码)服务器端验证凭据是否正确
  3. 如果凭据正确,请使用jwt密钥为此用户签署JWT令牌。
  4. 将创建的jwt令牌作为对localStorage中的client.
  5. Store

JWT令牌的响应发送,并将其添加到标头以供将来请求使用。<

  1. G216

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

为传入请求创建验证令牌环境variable

  • Creating a sign-in route

  • Creating a
  1. 的中间件验证令牌

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

JWT_SECRET=bX7fsuHzOksB27Pwh31qmazMsalw4bchu7Ft1X4PMOhO23Zq8nwBKA0FZQOK

创建接口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内置工具实现安全和良好的解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56315586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档