#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. Спасибо Джонатану Аквети Окину за вдохновение.