Ajax Auth перенаправление на Laravel 5.6
У меня есть кнопка Like, которая запускает сообщение Ajax, этот маршрут защищен auth: API middleware:
Myproject / routes / api.php
Route::group(['middleware' => ['auth:api']], function () {
Route::post('/v1/like', 'APIController@set_like');
});
Когда аутентифицированный пользователь нажимает кнопку like, никаких проблем, все работает гладко. Но когда гости нажимают кнопку, я перенаправляю их на страницу входа через Javascript, и после аутентификации они перенаправляются на страницу, указанную в RedirectIfAuthenticated middleware, поэтому обычно на /home.
Я модифицировал это промежуточное по следующим образом: образом:
Myproject / app / Http / Middleware / RedirectIfAuthenticated.php
<?php
namespace AppHttpMiddleware;
use Closure;
use IlluminateSupportFacadesAuth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param IlluminateHttpRequest $request
* @param Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect()->intended('/home');
}
return $next($request);
}
}
Мой вызов Ajax таков:
var toggleLike = function(){
var token = USER_TOKEN; //javascript variable
var current_type = $(thisLikeable).attr("data-type");
var current_id = $(thisLikeable).attr("data-id");
var jqxhr = $.post( APP_URL + "/api/v1/like", {api_token: token, type: current_type, id: current_id}, function(data) {
setLikeAppearance(data.message);
})
.fail(function(xhr, status, error){
if (xhr.status == 401) {
window.location = APP_URL + "/login" ;
}
});
};
Проблема здесь заключается в функции intended (), которая для вызовов Ajax не хранит правильную переменную сеанса, и я не выясняю, как ее правильно установить.
Я явно упускаю что-то очевидное, может кто-нибудь помочь?
Ура!
EDIT
Чего я хочу добиться, так это:
- гость находится в / / mysite / blabla
- щелчки Как кнопка
- перенаправляется на login
- вход в систему (или регистрация)
- перенаправляется на / / mysite / blabla с подобным уже запущенным на
3 ответов:
Дело в том, что в API сеансы не управляются или, другими словами, они не имеют состояния. Таким образом, промежуточное программное обеспечение сеанса не реализовано на платформе Laravel для запросов API. Хотя вы можете добавить вручную, он не простаивает в использовании. Поэтому, если API не использует сеансы и использует перенаправление, fronted не знает об этом, так как API и frontend работают как два отдельных приложения. Таким образом, вам нужно отправить frontend статус ответа и позволить frontend обрабатывать перенаправление, как вы это сделали с Аякс. просто удалите редирект, если он не прошел проверку подлинности, и позвольте API создать несанкционированное исключение. затем из обработчика обработайте несанкционированное исключение.
Вот как это сделать.
Добавьте это в приложение/исключения/обработчик.php
/** * Convert an authentication exception into an unauthenticated response. * * @param \Illuminate\Http\Request $request * @param \Illuminate\Auth\AuthenticationException $exception * @return \Illuminate\Http\Response */ protected function unauthenticated($request, AuthenticationException $exception) { if ($request->expectsJson()) { return response()->json(['error' => 'Unauthenticated.'], 401); } return redirect()->guest('login'); }Это отправит пользователю 401 с сообщением, не прошедшим проверку подлинности, если запрос был json (API request), иначе (если веб-запрос) перенаправит на login
Проверьте метод
renderниже или проверьте его из источника, чтобы понять что происходит? когда возникает несанкционированное исключение, мы говорим проверить тип запроса, и если это запрос API, мы посылаем ответ json с кодом состояния 401. Так что знайте от frontend мы могли бы перенаправить usee на страницу входа после просмотра кода состояния 401.Из источника
/** * Render an exception into a response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Symfony\Component\HttpFoundation\Response */ public function render($request, Exception $e) { if (method_exists($e, 'render') && $response = $e->render($request)) { return Router::toResponse($request, $response); } elseif ($e instanceof Responsable) { return $e->toResponse($request); } $e = $this->prepareException($e); if ($e instanceof HttpResponseException) { return $e->getResponse(); } elseif ($e instanceof AuthenticationException) { return $this->unauthenticated($request, $e); } elseif ($e instanceof ValidationException) { return $this->convertValidationExceptionToResponse($e, $request); } return $request->expectsJson() ? $this->prepareJsonResponse($request, $e) : $this->prepareResponse($request, $e); }ПОСЛЕ РЕДАКТИРОВАНИЯ
Предназначенный
method()предназначен только для веб-маршрутов, поскольку он использует сеанс для извлечения целевого маршрута или передаваемого вручную значения. Вот метод intended ()./** * Create a new redirect response to the previously intended location. * * @param string $default * @param int $status * @param array $headers * @param bool $secure * @return \Illuminate\Http\RedirectResponse */ public function intended($default = '/', $status = 302, $headers = [], $secure = null) { $path = $this->session->pull('url.intended', $default); return $this->to($path, $status, $headers, $secure); }Чтобы добиться перенаправления на страницу, с которой приходит пользователь, вы можете
1-вручную передать некоторые запросы с url, как
/login?redirect=like(not the url, just a mapping for /comments/like url)&value=true(true is liked, false is unliked)и обрабатывать его вручную.2-получить и проверить параметры запроса из url
3-Используйте метод to () для передачи предполагаемого url вместо использования предполагаемого (). вот метод to (). (см. 4, чтобы увидеть рекомендуемый способ)
/** * Create a new redirect response to the given path. * * @param string $path * @param int $status * @param array $headers * @param bool $secure * @return \Illuminate\Http\RedirectResponse */ public function to($path, $status = 302, $headers = [], $secure = null) { return $this->createRedirect($this->generator->to($path, [], $secure), $status, $headers); }4-но, я бы рекомендовал отправить url перенаправления (я имею в виду отображение ex: like) как ответ на frontend и пусть frontend обрабатывает перенаправление. как перенаправление API будет работать, если API используется только веб-сайтами. Предположим, если вы используете этот же api для мобильного приложения, интересно, как будет работать API redirect. Это не работа API для перенаправления, если только это не для таких вещей, как аутентификация OAuth, в которой был бы указан url перенаправления.
Не забудьте санировать параметры url, чтобы блокировать XSS, как и все остальное. Лучше отправьте некоторые значения и сопоставьте их с URL-адресами. Как
[ //like is mapping //comments/like is the actual url 'like' => 'comments/like' ], то получим преобразование адресов из массива или использовать сопоставления сайте.
Если кнопка не предназначена для гостя, то вы не должны отображать ее на странице. Вместо этого вы должны сделать ссылку для входа в систему, а затем, если пользователь войдет в систему, вы перенаправите его туда, где он был раньше. Теперь пользователь может видеть и нажимать на кнопку.
Вы можете внести изменения в свой RedirectIfAuthenticated.php Чтобы отличить Ajax вызов и обычный логин, как это:
namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class RedirectIfAuthenticated { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null $guard * @return mixed */ public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { if ($request->has('api_token')) { // do whatever you want return response()->json('some response'); } return redirect()->intended('/home'); } return $next($request); } }Обновление:
Другое решение-удалитьAuth middleware из вашего маршрута. В функции APIController@set_like вручную войдите в систему пользователя, запустите like и верните ответ json.
Comments