Обновление токена Laravel-vue JWT - PullRequest
0 голосов
/ 19 октября 2018

Я использую jwtAuth пакет от Tymon для обработки Auth от моего внутреннего интерфейса Laravel до vue spa-интерфейса, я создаю AuthController, который в значительной степени беру из документации и просто немного подправляюэтого, чтобы удовлетворить мои потребности.И все отлично работает от входа до выхода из системы и когда токен истекает.

Вопрос в том, что я вижу, что на этом контроллере есть функция обновления токена, которая, если мое предположение верно, это обновляет текущий токен, который уже есть у клиента.Но как это сделать?как мне справиться с этим токеном обновления на моем интерфейсе?Так как досадно, что каждые 60 минут (по умолчанию время жизни токена) будет выбрасываться 401.

Я хочу, возможно, каждый раз, когда пользователь делает запрос на бэкэнд, он обновляет токен или увеличиваетвремя жизни токена.Таким образом, срок действия токена истекает только в том случае, если пользователь простаивает все 60 минут.

Можем ли мы это сделать?и это лучшая практика?Я совсем новичок во всем jwt и в токене, в прошлом я полагаюсь только на токен Laravel до истечения срока его действия, так как я не работаю со спа, но передний конец лезвия, так что в основном не нужно возиться сспособ аутентификации пользователя с помощью laravel.

Для дополнительной информации здесь приведен каждый файл, который, я думаю, имеет какое-либо отношение ко всей аутентификации.

Вот мой authcontroller

<?php

namespace App\Http\Controllers;

use DB;
use Hash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Input;
use App\Http\Controllers\Controller;
use App\User;
use Response;

class Authcontroller extends Controller
{
    /**
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }

    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request(['username', 'password']);

        if (! $token = auth('api')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }

    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        return response()->json(auth('api')->user());
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth('api')->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }

    /**
     * Refresh a token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth('api')->refresh());
    }

    /**
     * Get the token array structure.
     *
     * @param  string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        $id = auth('api')->user()->getId();
        $kelas = User::with('pus','cu')->findOrFail($id);

        return response()->json([
            'access_token' => $token,
            'user' => $kelas,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ]);
    }

    public function guard()
    {
        return Auth::Guard('api');
    }

}

Вот мой маршрут API

Route::group(['prefix' => 'auth'],function($router){
    Route::post('/login', 'AuthController@login');
    Route::post('/logout', 'AuthController@logout');
    Route::post('/refresh', 'AuthController@refresh');
    Route::get('/me', 'AuthController@me');
});

А вот мой vue general.js файл, который обрабатывает маршрут и также дает заголовок Axios

export function initialize(store, router) {
  router.beforeEach((to, from, next) => {
      const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
      const currentUser = store.state.auth.currentUser;

      if(requiresAuth && !currentUser) {
          next('/login');
      } else if(to.path == '/login' && currentUser) {
          next('/');
      } else {
          next();
      }
  });

  axios.interceptors.response.use(null, (error) => {
      if (error.response.status == 401) {
          store.dispatch('auth/logout');
          router.push('/login');
      }

      return Promise.reject(error);
  });

  if (store.state.auth.currentUser) {
      setAuthorization(store.state.auth.currentUser.token);
  }
}

export function setAuthorization(token) {
  axios.defaults.headers.common["Authorization"] = `Bearer ${token}`
}

А вот auth.jsчто обрабатывать логин

import { setAuthorization } from "./general";

export function login(credentials){
  return new Promise((res,rej) => {
    axios.post('/api/auth/login', credentials)
      .then((response) => {
        setAuthorization(response.data.access_token);
        res(response.data);
      })
      .catch((err) => {
        rej("Username atau password salah");
      })
  })
}

1 Ответ

0 голосов
/ 19 октября 2018

Вы можете настроить срок действия токена (от .env до JWT_TTL) и время обновления (JWT_REFRESH_TTL) в соответствии с вашими потребностями.И убедитесь, что токен действителен и / или нуждается в обновлении в промежуточном программном обеспечении, чтобы токен обновлялся сразу же, как и должен.

Относительно того, является ли это хорошей практикой, см. Комментарии к JWT_REFRESH_TTL в вашем проекте Laravel config/jwt.php.

Решение, которое мне пригодилось, состояло в том, чтобы использовать пользовательское Middleware, которое расширяет Tymon\JWTAuth\Http\Middleware\BaseMiddleware.Шаблон будет выглядеть примерно так:

Class TryTokenRefresh extends BaseMiddleware
{
    public function handle($request, Closure $next)
    {
        $newToken = $this->tryRefresh($request);
        if ($newToken) {
           // in case there's anything further to be done with the token
           // we want that code to have a valid one
           $request->headers->set('Authorization', 'Bearer ' . $newToken);
        }

        ...
        ...
        $response = $next($request);
        ...
        ...

        if ($newToken) {
            // send new token back to frontend
            $response->headers->set('Authorization', $newToken);
        }

        return $response;
    }

    // Refresh the token
    protected function tryRefresh()
    {
        try {
            $token = $this->auth->parseToken()->refresh();
            return $token;
        } catch (JWTException $e) {
            // token expired? force logout on frontend
            throw new AuthenticationException();
        }

        return null;
    }

На внешнем интерфейсе это так же просто, как искать заголовок Authorization в ответе:

// check for the `Authorization` header in each response - refresh on frontend if found
axios.interceptors.response.use((response) => {
  let headers = response.headers

  // your 401 check here
  // token refresh - update client session
  if (headers.authorization !== undefined) {
   setAuthorization(headers.authorization);
  }

  return response
})

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...