В приложении laravel 7 backend rest api app я использую jwt-auth, и у меня есть проблема, что при входе в систему я могу работать во внешнем интерфейсе, но через 1 час я получаю ошибку TOKEN_EXPIRED.
1) Я пытался установить время сеанса больше, но не смог. На стадии разработки мне нужно время сеанса более 1 часа. В прямом эфире я установлю время сеанса 30 минут.
2) Я ожидал, что сессия больше на 1 час от последнего запроса зарегистрированного пользователя к серверу, но не от входа в систему
У меня есть метод обновления, реализованный ниже, но похоже, что обновление не работает...
приложение/Http/Контроллеры/API/AuthController.php:
<?php
namespace App\Http\Controllers\API;
use App\library\CheckValueType;
use App\Settings;
use Auth;
use Config;
use DB;
use Validator;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Support\Str;
use App\UserGroup;
use App\Http\Resources\UserCollection;
use Avatar;
use Storage;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('jwt.auth', ['except' => ['login', 'register', 'activate']]);
}
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ($token = $this->guard('api')->attempt($credentials)) {
$loggedUser = $this->guard('api')->user();
if ($loggedUser->status != 'A') {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
$loggedUser->last_logged = Carbon::now(config('app.timezone'));
$loggedUser->save();
$userGroupsCount = UserGroup
::getByUserId($loggedUser->id)
->count();
if ($userGroupsCount == 0) {
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
return $this->respondWithToken($token);
}
return response()->json(['error' => 'Unauthorized'], HTTP_RESPONSE_NOT_UNAUTHORIZED);
}
public function me()
{
return response()->json($this->guard('api')->user());
}
public function logout()
{
$this->guard('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken($this->guard()->refresh());
}
protected function respondWithToken($token)
{
$loggedUser = $this->guard()->user();
$user_avatar_path = 'public/' . User::getUserAvatarPath($loggedUser->id, $loggedUser->avatar);
$filenameData = User::setUserAvatarProps($loggedUser->id, $loggedUser->avatar, true);
$usersGroups = User::getUserGroupByUserId($loggedUser->id, false);
return response()->json([
'access_token' => $token,
'user' => $loggedUser,
'token_type' => 'bearer',
'user_avatar_path' => $user_avatar_path,
'filenameData' => $filenameData,
'usersGroups' => $usersGroups,
'expires_in' => $this->guard('api')->factory()->getTTL() * 999360 // I SET VERY BIG VALUE
]);
}
public function guard()
{
return \Auth::Guard('api');
}
В /config/auth.php:
<?php
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 99360, // I SET BIG VALUE
'throttle' => 98860,
],
],
'password_timeout' => 10800, // I SET BIG VALUE
В app/Exceptions/Handler.php у меня есть:
public function render($request, Throwable $exception)
{
if ($exception instanceof UnauthorizedHttpException) {
if ($exception->getPrevious() instanceof TokenExpiredException) {
\Log::info( '-2 UnauthorizedHttpException TokenExpiredException::' ); // I SEE THIS ERROR LOGGED
return response()->json(['error' => 'TOKEN_EXPIRED'], $exception->getStatusCode());
У меня есть :
"laravel/framework": "^7.0",
"tymon/jwt-auth": "^1.0.0",
Что не так в моей конфигурации?
ИЗМЕНЕНО:
Я добавил файл app/Http/Middleware/JwtMiddleware.php с содержимым и 1 строкой журнала ошибок:
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
class JwtMiddleware extends BaseMiddleware
{
public function handle($request, Closure $next)
{
try {
if (! $user = $this->auth->parseToken()->authenticate()) {
return response()->json(['success' => false, 'error' => __('Invalid User.')]);
}
} catch (TokenExpiredException $e) {
try {
$refreshed = $this->auth->refresh($this->auth->getToken());
$user = $this->auth->setToken($refreshed)->toUser();
header('Authorization: Bearer ' . $refreshed);
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => __('Could not generate refresh token')]);
}
} catch (JWTException $e) {
\Log::info( '-1 JwtMiddleware$e->getMessage() ::' . print_r( $e->getMessage(), true ) );
return response()->json(['success' => false, 'error' => __('Invalid request')]);
}
return $next($request);
}
}
и я добавил в файл app/Http/Kernel.php:
...
protected $middleware = [
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\JwtMiddleware::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class
];
...
and running the page site is broken and I see lines in log :
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
[2020-05-27 17:08:33] local.INFO: -1 JwtMiddleware$e->getMessage() ::The token could not be parsed from the request
Может быть конфликт с кодом app/Http/Controllers/API/AuthController.php? Как это можно исправить?
ИЗМЕНЕНО №2: Спасибо! Я исправил ошибку и в .env добавил строки:
JWT_TTL=20 # 20 minutes
JWT_REFRESH_TTL=20160 # 2 weeks
и очистив кеш, я снова вошел в систему, и в результате во время работы в приложении я не выходил из системы в течение 20 минут, но когда я оставил приложение открытым, не работая с ним в течение примерно 30 минут, я мог продолжать работать без входа в систему, как я и ожидал. Это другие варианты?
ИЗМЕНЕНО №3: в клиентской части моего файла vuejs я добавил перехватчики запросов в src/App.vue:
created() {
let self = this
this.$http.interceptors.response.use(undefined, function (error) {
return new Promise(function (/*resolve, reject*/) {
if (typeof error.response.status !== 'undefined' && error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
let splitted0 = self.getSplitted(error.response.config.url, '/login', 0)
if (splitted0 == '') { // not move from login page
self.$router.push('/login') // DEBUGGING
}
}
if (typeof error.response.status !== 'undefined') {
if (error.response.status === 401) {
self.$store.dispatch('logout') // DEBUGGING
self.showPopupMessage('Access', 'Not authorized !', 'warn')
self.$router.push('/login') // DEBUGGING
}
}
throw error
})
})
}, // created() {
Ловлю в нем ошибку 401 и интересно можно ли перехватить запрос с сервера
header('Authorization: Bearer ' . $refreshed);
а записать в новое значение access_token из $refreshed? Но как мне его поймать? Но какой-то специальный код запроса на возврат?
Спасибо!
php artisan config:clear
иphp artisan cache:clear
, чтобы увидеть, как изменения вступят в силу. - person Digvijay   schedule 27.05.2020