При использовании JWT с Laravel и Axios JWT работает, но другие маршруты всегда возвращают 401 не прошедший проверку подлинности

#laravel #axios #jwt

#laravel #axios #jwt

Вопрос:

Я успешно внедрил JWT в Laravel, и все работает нормально. Вход в систему, выход из системы.

Но каждый раз, когда я хочу добавить новый маршрут в свой routes/api.php и попытаться использовать его с контроллером, я получаю 401 Unauthenticated . Кажется, что контроллер не адресован, потому что не var_dump возвращается.

Мой config/auth.php

 'guards' => [
   'web' => [
       'driver' => 'session',
       'provider' => 'users',
   ],

   'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],
  

Мой запрос:

 let myConfig = {
    headers: {
        Authorization: "Bearer "   'JWT_SECRET'
    }
}

axios.get('http://localhost/api/getcashboxes', myConfig)
.then(res => {
    console.log(res.data)
}).catch(err => {
    console.log(err)
})
  

Мой routes/api.php

 use IlluminateHttpRequest;

Route::get('getcashboxes', 'CashboxController@getcashboxes')->name('getcashboxes');

Route::group(['prefix' => 'auth'], function ($router) {

    Route::post('login', 'AuthController@login');
    Route::post('logout', 'AuthController@logout');
    Route::post('refresh', 'AuthController@refresh');
    Route::post('me', 'AuthController@me');

});
  

Мой CashboxController.php

 namespace AppHttpControllers;
use IlluminateSupportFacadesAuth;
use AppHttpControllersController;
use IlluminateHttpRequest;

class CashboxController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
        //$this->middleware('auth:api'); //Does not work too
    }

    public function getcashboxes()
    {
        var_dump("Hello World :)");
    }
}
  

Заголовок запроса:

 Accept
    application/json, text/plain, 
Accept-Encoding
    gzip, deflate
Accept-Language
    de,en-US;q=0.7,en;q=0.3
Authorization
    Bearer 5zqyH1BrQUbiDRefurc5XaduzaTyCXPlcPXbodDHhsgdjJHU1dDHhsgdjefur
Cache-Control
    max-age=0
Connection
    keep-alive
Cookie
    XSRF-TOKEN=eyJpdiI6IlVjRFwvYkRvaSs3cDBCVFkxMFZtZkhRPT0iLCJ2YWx1ZSI6Imw4WlZ3RlwvVjNQemZOaTRQXC84MDlrd01uc0dFeUZ4eCtuR29jcWFqTGZBY3RkdzdFdFpzWjB4UDZOQzhQYXRTUCIsIm1hYyI6ImE5ODFkODM1ODU3M2Q3ZDEyZDY1NjdiYTY3ZGJkN2FlNGIzYWRiZTcxNjI4ODc3MmZkYzg3MGZjMzhmODlhODkifQ%3D%3D; buywatchvue_session=eyJpdiI6IjFSb25ZdmthalF2Tm1TWjM4cnUzRkE9PSIsInZhbHVlIjoiQms0SDNGNlFPcXM1YVR2MTZzeEJpRkc1MnlPeFlGOW5IRlRVR0pTZWI3MUk2XC9RMUdsYVp5SWQyTnJRcitoazIiLCJtYWMiOiI0ZmYyNjQxOWY0NjAxNzM4NzY2YzBmYjY2Mjc2OTcyNTE0ZjVkYzdlMDU2YzE0MWE4Y2U2MzZmNTFkNzU2MWY4In0%3D; laravel_session=eyJpdiI6Ik4wNGRJM3Q5QU5KRUlIbWZoaUE4VkE9PSIsInZhbHVlIjoiNmNLb09JeU5DRksxM1VNMElPNDNQb1NseVNJYWdTdXpZdnZyS1RuMlVRY043OUJcLzREMXhkaWR3TmR6ZklWaWIiLCJtYWMiOiJmYWViNzIxMmZjYTU1N2UwYmI2OTU3YzAyNmFmNzM3NjAyMzY5N2Q2MTAyMzEwNzc1MDZlZWQzMjE4YWZiN2UyIn0%3D
Host
    localhost
Referer
    http://localhost
User-Agent
    Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
X-CSRF-TOKEN
    DClSR93LzbeM4SZQ9OzZJ89s5jtiNFOfkWabYMSJ
X-Requested-With
    XMLHttpRequest
X-XSRF-TOKEN
    eyJpdiI6IlVjRFwvYkRvaSs3cDBCVFkxMFZtZkhRPT0iLCJ2YWx1ZSI6Imw4WlZ3RlwvVjNQemZOaTRQXC84MDlrd01uc0dFeUZ4eCtuR29jcWFqTGZBY3RkdzdFdFpzWjB4UDZOQzhQYXRTUCIsIm1hYyI6ImE5ODFkODM1ODU3M2Q3ZDEyZDY1NjdiYTY3ZGJkN2FlNGIzYWRiZTcxNjI4ODc3MmZkYzg3MGZjMzhmODlhODkifQ==
  

Заголовок ответа:

 Cache-Control
    no-cache, private
Connection
    Keep-Alive
Content-Length
    30
Content-Type
    application/json
Date
    Sat, 22 Aug 2020 14:12:25 GMT
Keep-Alive
    timeout=5, max=99
Server
    Apache/2.4.37 (Win32) OpenSSL/1.1.1a PHP/7.3.0
Vary
    Authorization
X-Powered-By
    PHP/7.3.0
  

У кого-нибудь есть идея?

Комментарии:

1. если вы проверяете свои заголовки, видите ли вы отправленный токен?

2. Я добавил заголовки в свой пост

3. У меня была похожая проблема с этой проблемой. Я думаю, что происходит то, что токен не попадает на серверную часть, отсюда и значение 401. Я решил это, создав заголовки по умолчанию с помощью axios.

4. хм, ты можешь показать, что ты имеешь в виду?

5. Пожалуйста, проверьте мой ответ и дайте мне знать, если это поможет вам.

Ответ №1:

Вы можете создать экземпляр axios и использовать его, как я сделал.

 const instance = axios.create({
baseURL: 'http://localhost/api'
});

instance.defaults.headers.common['Authorization'] = `Bearer ${token}`;

instance.get('/getcashboxes')
.then(res => {
console.log(res.data)
}).catch(err => {
console.log(err)
 })
  

Пожалуйста, дайте мне знать, если это поможет вам устранить проблему.

Комментарии:

1. Хм, это не сработает, но … можете ли вы сказать мне, откуда вы получаете ${JWT_SECRET} и как это выглядит? Для меня JWT_SECRET находится в .env , и я просто скопировал его для тестирования.

2. Извините, почему вы говорите, что это не сработает? предполагается, что переменной там является токен. Извините. где вы храните токен после его получения?

3. Я думал, что это то, что вы передавали в качестве своего токена.

4. Извините, не «этого не будет», я имел в виду «не было». Теперь мне интересно, просто ли я использую неправильный токен. Разве это не должно выглядеть aaaa.bbbb.cccc? Как вы получаете токен из .env-файла?

5. Можете ли вы сказать мне, где вы храните свой токен после его получения? Возможно, вы используете неправильный токен, возможно, срок действия токена истек. Да, токены jwt выглядят как aaaa.bbb.cccc. Но где вы его храните?

Ответ №2:

Я нашел решение. Это был недостаток знаний о том, как работают веб-токены JSON (JWT).

Принцип объясняется просто: если пользователь вошел в систему с сервера, он получает JWT обратно. Теперь этот JWT должен быть сохранен на стороне клиента либо как cookie, либо в локальном хранилище. Это необходимо для последующих запросов сервера.

Если на сервер отправляется запрос, требующий авторизации, JWT должен быть отправлен в заголовке.

Поэтому он должен быть прочитан из файла cookie или локального хранилища. С Laravel , Vue , Vuex , Axios и local storage это может выглядеть следующим образом:

Получить токен с сервера ( AuthController.php ):

 public function login()
{
    $credentials = request(['email', 'password']);

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

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

Изменение входа в vuex ( store.js ):

 mutations: {
    loginSuccess(state, payload) {
        state.auth_error = null;
        state.isLoggedIn = true;
        state.loading = false;
        state.currentUser = Object.assign({}, payload.user, {token: payload.access_token});
    
        localStorage.setItem("user", JSON.stringify(state.currentUser));
    },
},
  

Получаем локального пользователя, включающего токен JWT:

 function getLocalUser() {
    const userStr = localStorage.getItem("user");

    if(!userStr) {
        return null;
    }

    return JSON.parse(userStr);
}
  

Создайте axios-запрос, используя JWT-токен из локального хранилища:

 const instance = axios.create({
    baseURL: 'http://localhost/api'
});

instance.defaults.headers.common['Authorization'] = `Bearer ${getLocalUser().token}`;

instance.get('/test')
.then(res => {
    console.log(res.data)
}).catch(err => {
    console.log(err)
})
  

Я надеюсь, что смогу кому-нибудь помочь с этим. В противном случае здесь есть дополнительная информация о JWT. Спасибо Джонатану Аквети Окину за вдохновение.