Ich baue eine Single-Page-App mit Vue (2.5) mit Laravel (5.5) als Backend. Alles funktioniert gut, außer dass man sich nach dem Ausloggen direkt wieder anmeldet. In diesem Fall schlägt der Aufruf von/api/user (zum Abrufen der Kontoinformationen des Benutzers und zum erneuten Überprüfen der Identität des Benutzers) mit einem nicht autorisierten 401 fehl (obwohl die Anmeldung erfolgreich war). Als Antwort wird der Benutzer direkt zum Anmeldebildschirm zurückgeworfen (ich habe diese Maßnahme selbst als Reaktion auf 401 Antworten geschrieben).Authentifizierungstoken für ein Vue.js SPA mit Laravel für das Backend aktualisieren
Wie funktioniert es, sich abzumelden, aktualisieren Sie die Seite mit Strg/Cmd + R, und melden Sie sich dann erneut an. Die Tatsache, dass eine Seitenaktualisierung mein Problem behebt, gibt mir Anlass zu der Annahme, dass ich die Aktualisierung von X-CSRF-TOKEN nicht korrekt handle oder bestimmte Cookies vergesse, die Laravel verwendet (wie beschrieben here).
Dies ist ein Codeausschnitt des Login-Formulars, das ausgeführt wird, nachdem ein Benutzer auf die Login-Schaltfläche geklickt hat.
login(){
// Copy the form data
const data = {...this.user};
// If remember is false, don't send the parameter to the server
if(data.remember === false){
delete data.remember;
}
this.authenticating = true;
this.authenticate(data)
.then(this.refreshTokens)
.catch(error => {
this.authenticating = false;
if(error.response && [422, 423].includes(error.response.status)){
this.validationErrors = error.response.data.errors;
this.showErrorMessage(error.response.data.message);
}else{
this.showErrorMessage(error.message);
}
});
},
refreshTokens(){
return new Promise((resolve, reject) => {
axios.get('/refreshtokens')
.then(response => {
window.Laravel.csrfToken = response.data.csrfToken;
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = response.data.csrfToken;
this.authenticating = false;
this.$router.replace(this.$route.query.redirect || '/');
return resolve(response);
})
.catch(error => {
this.showErrorMessage(error.message);
reject(error);
});
});
},
die authenticate()
Methode ist eine vuex Aktion, die den Login-Endpunkt an der Laravel Seite aufruft.
Der/refreshTokens Endpunkt ruft einfach diese Laravel Controller-Funktion, die die CSRF-Token des aktuell angemeldeten Benutzers zurückgibt:
public function getCsrfToken(){
return ['csrfToken' => csrf_token()];
}
Nachdem die Tokens haben erneut abgerufen wurde, der Benutzer auf die Hauptseite umgeleitet wird (oder eine andere Seite, falls mitgeliefert) mit this.$router.replace(this.$route.query.redirect || '/');
und dort wird die api/user
Funktion aufgerufen, um die Daten des aktuell angemeldeten Benutzers zu prüfen.
Gibt es noch andere Maßnahmen, die ich ergreifen sollte, um diese Arbeit zu machen, die ich übersehe?
Danke für jede Hilfe!
EDIT am: 07 Nov 2017
Nachdem alle Anregungen, würde Ich mag einige Informationen hinzuzufügen. Ich verwende Passport zur Authentifizierung auf der Laravel-Seite, und die CreateFreshApiToken-Middleware ist vorhanden.
Ich habe mir die von meiner App gesetzten Cookies angeschaut, insbesondere die laravel_token
, von der gesagt wird, dass sie den verschlüsselten JWT enthält, den Passport zur Authentifizierung von API-Anfragen aus Ihrer JavaScript-Anwendung verwendet. Beim Ausloggen wird der Laravel_Token-Cookie gelöscht. Beim erneuten Einloggen direkt danach (mit Axios zum Senden einer AJAX-Post-Anfrage) wird keine neue laravel_token
eingestellt, weshalb der Benutzer nicht authentifiziert wird. Mir ist bekannt, dass Laravel den Cookie nicht auf die Anmelde-POST-Anfrage setzt, sondern die GET-Anfrage an/refreshTokens (die nicht bewacht wird) direkt danach sollte den Cookie setzen. Dies scheint jedoch nicht zu geschehen.
Ich habe versucht, die Verzögerung zwischen der Anfrage an und die Anfrage an /api/user
, vielleicht geben Sie dem Server etwas Zeit, um die Dinge in Ordnung zu bringen, aber ohne Erfolg.
Der Vollständigkeit halber, hier ist meine Auth \ LoginController, dass die Anmeldeanforderung serverseitige Handhabung:
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
// $this->middleware('guest')->except('logout');
}
/**
* Get the needed authorization credentials from the request.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function credentials(\Illuminate\Http\Request $request)
{
//return $request->only($this->username(), 'password');
return ['email' => $request->{$this->username()}, 'password' => $request->password, 'active' => 1];
}
/**
* The user has been authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $user
* @return mixed
*/
protected function authenticated(\Illuminate\Http\Request $request, $user)
{
$user->last_login = \Carbon\Carbon::now();
$user->timestamps = false;
$user->save();
$user->timestamps = true;
return (new UserResource($user))->additional(
['permissions' => $user->getUIPermissions()]
);
}
/**
* Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function logout(\Illuminate\Http\Request $request)
{
$this->guard()->logout();
$request->session()->invalidate();
}
}
Wie ist die Abmeldefunktion implementiert? – vtosh
Es ruft die Abmeldefunktion von Laravel mit einer Postanforderung auf. so einfach 'axios.post ('/ logout')'; –
Wenn Sie sich die Ajax-Anfragen für Abmelden/Anmelden ansehen, sehen Sie, dass ein neues Token von/refreshtokens generiert und zurückgegeben wird, und ist dies das Token, das bei den nachfolgenden (und fehlgeschlagenen) Aufrufen an den Server verwendet wird? –