Laravel Passport промежуточное программное обеспечение защищенных маршрутов "Неаутентифицированные" проблема
Я использую Laravel Passport для аутентификации, поэтому я помещаю свои маршруты в защиту промежуточного программного обеспечения.
ОБНОВЛЕНО
Чтобы было понятно, я добавляю UsersController тоже.
public function getUser()
{
$users = Auth::user();
return response()->json($users);
}
//
Route::group(['prefix' => 'v1', 'middleware' => 'auth:api'], function () {
/* users */
Route::get('/users', 'Api\[email protected]');
/* fetch */
Route::get('/articles', 'Api\[email protected]');
Route::get('/article/{id}', 'Api\[email protected]');
});
Конечно, мне нужно войти в систему, или я не вижу защищенные маршруты. Я сделал AuthController
и внутри него функцию входа в систему контроллера.
контроллер
public function login(Request $request)
{
$http = new \GuzzleHttp\Client;
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $request->email,
'password' => $request->password,
]
]);
return $response->getBody();
} catch (\GuzzleHttp\Exception\BadResponseException $e) {
if ($e->getCode() === 400) {
return response()->json('Invalid Request. Please enter a username or a password.', $e->getCode());
}
if ($e->getCode() === 401) {
return response()->json('Your credentials are incorrect. Please try again', $e->getCode());
}
return response()->json('Something went wrong on the server.', $e->getCode());
}
}
В интерфейсе моего vuex у меня есть призыв к действию.
retrieveToken(context, credentials){
return new Promise((resolve, reject) => {
axios.post("api/v1/login", {
email: credentials.username,
password: credentials.password,
})
.then(response => {
const token = response.data.access_token;
localStorage.setItem("access_token", token);
context.commit("retrieveToken", token);
resolve(resolve);
})
.catch(error => {
console.log(error);
reject(response);
})
})
},
Все отлично. Я храню токен и использую его для входа в систему и удаляю его для выхода из системы. Но на сервере чего-то не хватает. Потому что, даже если войти, я все еще не вижу защищенные маршруты. Laravel Auth не знает, что пользователь вошел в систему.
Где мне поставить токен в шапку? Внутри контроллера или метода входа? Или мне нужно сделать что-то еще?
Ответы
Ответ 1
Также вошедший в систему пользователь видит страницы, которые может видеть только авторизованный пользователь.
Как ты это делаешь? Если пользователь может видеть то, что может видеть пользователь авторизации, что означает, что вы делаете GET
с токеном аутентификации правильно? Если вы используете паспорт, вы должны поместить токен в заголовок авторизации.
axios.defaults.headers.common.Authorization = 'Bearer ${token}';
Используйте это, чтобы добавить токен в ваш запрос по всем аксиосам после того, как вы войдете в систему, и тогда все будет хорошо.
Ответ 2
В компоненте входа используйте
methods: {
login() {
var instance = axios.create({
baseURL: "http://apiendpoint.com/api/"
});
instance
.post("/admin-login", {
email: this.username,
password: this.password,
device_type: "Web",
device_token: "Web"
})
.then(response => {
// console.log(response);
localStorage.setItem("token", response.data.data.token);
this.$router.push("/");
})
.catch(error => {
console.log(error);
});
}
},
Затем определите конфигурацию axios в файле как Repository.js, который можно использовать со всеми ресурсами.
/******************** Repository js ****************/
import axios from "axios";
import router from "./router";
const baseDomain = "http://tetragolf-api.cubettech.in";
const baseURL = '${baseDomain}/api';
const api = axios.create({
baseURL, // headers: {
// 'Authorization': 'Bearer ' + localStorage.getItem('api_token')
// },
validateStatus: function(status) {
if (status == 401) {
router.push("/login");
} else {
return status;
}
}
});
api.interceptors.request.use(
function(config) {
const token = localStorage.getItem("token");
if (token == null) {
console.log("Token Is empty");
console.log("Redirecting to Login");
router.push({ name: "login" });
}
if (token) {
config.headers.Authorization = 'Bearer ${token}';
}
return config;
},
function(response) {
return response;
console.log(response);
},
function(error) {
console.log(error);
return error;
}
);
// Add a response interceptor
api.interceptors.response.use(
function(response) {
// Do something with response data
return response;
},
function(error) {
// Do something with response error
console.log("Error Found");
return Promise.reject(error);
}
);
export default api;
И определите все маршруты Vue в Router.
Ответ 3
Если вы просто используете API с помощью javascript, я бы предложил добавить промежуточное ПО CreateFreshApiToken
в вашу группу веб-промежуточного ПО.
Из документов:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
В противном случае, как уже говорили другие, обязательно включите заголовок Authorization и Content-Type в ваш запрос.
Ответ 4
Если вы используете аутентификацию по токену с паспортом laravel, всегда устанавливайте заголовок аутентификации (для любого клиентского вызова) Authorization = Bearer your_token
для защищенных маршрутов при вызове из клиента. Я делаю простой пример аутентификации с Laravel Passport и Vue.js и загружаю его на github, пожалуйста, проверьте его по этой ссылке. Я также рекомендую вам прочитать этот пост
Ваш логин в Laravel должен выглядеть так
public function login (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user) {
if (Hash::check($request->password, $user->password)) {
$token = $user->createToken('Laravel Password Grant Client')->accessToken;
$response = ['token' => $token];
return response($response, 200);
} else {
$response = "Password missmatch";
return response($response, 422);
}
} else {
$response = 'User does not exist';
return response($response, 422);
}
мои маршруты laravel, 'middleware' => ['json.response']
, я использую, чтобы форсировать json все данные
Route::group(['middleware' => ['json.response']], function () {
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
// public routes
Route::post('/login', 'Api\[email protected]')->name('login.api');
Route::post('/register', 'Api\[email protected]')->name('register.api');
// private routes
Route::middleware('auth:api')->group(function () {
Route::get('/logout', 'Api\[email protected]')->name('logout');
});
});
мои guards
в config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
тогда в vue вы можете использовать vuex для хранения токена и пользовательские данные для его повторного использования store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== 'production'
export default new Vuex.Store({
strict: debug,
state: {
auth: null,
token: null,
check:false
},
getters: {
auth: state => state.auth,
token: state => state.token,
},
mutations: {
SET_TOKEN(state, token) {
state.token = token
},
FETCH_auth_SUCCESS(state, auth) {
state.auth = auth
state.check = true
},
FETCH_auth_FAILURE(state) {
state.token = null
},
LOGOUT(state) {
state.auth = null
state.token = null
state.check = false
},
UPDATE_auth(state, { auth }) {
state.auth = auth
}
},
actions: {
saveToken({ commit, dispatch }, { token, remember }) {
commit('SET_TOKEN', token)
// if you need store token in cookie (remember me option)
// Cookies.set('token', token, { expires: remember ? 365 : null })
},
async fetchauth({ commit,state }) {
try {
axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
const { data } = await axios.get('/api/user')
commit('FETCH_auth_SUCCESS', data)
} catch (e) {
// Cookies.remove('token')
commit('FETCH_auth_FAILURE')
}
},
updateauth({ commit }, payload) {
commit('UPDATE_auth', payload)
},
async logout({ commit,state }) {
try {
axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
await axios.get('/api/logout')
} catch (e) {console.log(e) }
// Cookies.remove('token')
commit('LOGOUT')
},
}
});
Примечание. Я установил токен axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
на каждом вызове axios (защищенные маршруты), но вы можете сделать это глобально один раз.
Метод входа в vue
methods: {
login() {
console.log("Login");
axios
.post("/api/login", {
email: this.form.email,
password: this.form.password
})
.then(res => {
// save token to vuex
this.$store.dispatch("saveToken", { token: res.data.token });
// get user data, store in vuex
this.$store.dispatch("fetchauth");
// redirect
this.$router.push({path:'/dashboard'});
})
.catch(e => {
console.log(e);
});
}
}
Когда вы делаете вызов к защищенным маршрутам с помощью 'auth:api'
первую очередь вам нужно установить токен в заголовке, чтобы получить доступ к ресурсам. В axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
находится axios.defaults.headers.common.Authorization = 'Bearer ${state.token}';
,