javascript - Hur upptäcker jag om en användare redan är inloggad i Firebase?
Jag använder Firebase Node API i mina JavaScript-filer för Google-inloggning.
firebase.initializeApp(config);
let provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider);
Detta fungerar bra och användaren kan logga in med sina Google-uppgifter. När användaren besöker sidan igen öppnas popup-fönstret igen men eftersom han redan är inloggad stängs popup-fönstret utan att någon interaktion från användaren krävs. Finns det något sätt att kontrollera om det redan finns en inloggad användare innan popup-fönstret visas?
Svar #1
https://firebase.google.com/docs/auth/web/manage-users
Du måste lägga till en observatör för ändring av autentiseringstillstånd.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
Svar #2
Du kan också kontrollera om det finns en currentUser
var user = firebase.auth().currentUser;
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
Svar #3
Det är inte möjligt att säga om en användare kommer att vara inloggad när en sida börjar laddas, men det finns en lösning.
Du kan komma ihåg senaste autentiseringstillståndet i localStorage för att behålla det mellan sessioner och mellan flikar.
Sedan, när sidan börjar laddas, kan du optimistiskt anta att användaren kommer att loggas in automatiskt igen och skjuta upp dialogrutan tills du kan vara säker (dvs efter att onAuthStateChanged utlöses). Annars, om localStorage-nyckeln är tom, kan du visa dialogrutan direkt.
Firebase-onAuthStateChanged-händelsen kommer att utlösas ungefär 2 sekunder efter att sidan har laddats.
// User signed out in previous session, show dialog immediately because there will be no auto-login
if (!localStorage.getItem('myPage.expectSignIn')) showDialog() // or redirect to sign-in page
firebase.auth().onAuthStateChanged(user => {
if (user) {
// User just signed in, we should not display dialog next time because of firebase auto-login
localStorage.setItem('myPage.expectSignIn', '1')
} else {
// User just signed-out or auto-login failed, we will show sign-in form immediately the next time he loads the page
localStorage.removeItem('myPage.expectSignIn')
// Here implement logic to trigger the login dialog or redirect to sign-in page, if necessary. Don't redirect if dialog is already visible.
// e.g. showDialog()
}
})
Jag använder detta med React och react-router. Jag lade koden ovan i componentDidMount i min App root-komponent. Där, i renderingen, har jag några PrivateRoutes
<Router>
<Switch>
<PrivateRoute
exact path={routes.DASHBOARD}
component={pages.Dashboard}
/>
...
Och så här är min PrivateRoute implementerad:
export default function PrivateRoute(props) {
return firebase.auth().currentUser != null
? <Route {...props}/>
: localStorage.getItem('myPage.expectSignIn')
// if user is expected to sign in automatically, display Spinner, otherwise redirect to login page.
? <Spinner centered size={400}/>
: (
<>
Redirecting to sign in page.
{ location.replace(`/login?from=${props.path}`) }
</>
)
}
// Using router Redirect instead of location.replace
// <Redirect
// from={props.path}
// to={{pathname: routes.SIGN_IN, state: {from: props.path}}}
// />
Svar #4
Det finns inget behov av att använda funktionen onAuthStateChanged() i detta scenario.
Du kan enkelt upptäcka om användaren är inloggad eller inte genom att köra:
var user = firebase.auth().currentUser;
För dem som stöter på problemet med "returnerar null" är det bara för att du inte väntar på att Firebase-anropet ska slutföras.
Låt oss anta att du utför inloggningsåtgärden på Sida A och sedan anropar Sida B. På Sida B kan du köra följande JS-kod för att testa det förväntade beteendet:
var config = {
apiKey: "....",
authDomain: "...",
databaseURL: "...",
projectId: "..",
storageBucket: "..",
messagingSenderId: ".."
};
firebase.initializeApp(config);
$( document ).ready(function() {
console.log( "testing.." );
var user = firebase.auth().currentUser;
console.log(user);
});
Om användaren är inloggad kommer "var user" att innehålla den förväntade JSON-payloaden, annars kommer det bara att vara "null"
Och det är allt du behöver.
Hälsningar
Svar #5
Jag använder react och react-router-dom med loader-funktion, efter att ha uppdaterat sidan kan min loader inte ladda data från firestore eftersom firebase-appen behöver lite tid för att initialiseras. Jag hittade en enkel lösning. Jag ställer in auth-metoden innan jag kontrollerar om användaren är inloggad och det fungerar. Återigen, du behöver vänta på att firebase-appen ska stabilisera sig och denna auth-metod gör precis det, den väntar på att appen ska initialiseras. Här är min lösning, det är så enkelt:
export const getContacts = async () => {
await auth.authStateReady()
const currentUser = auth.currentUser
if (!currentUser) return false
// rest of code ...
}
await auth.authStateReady() är ett löfte och det kommer att vänta på att lösas med användare eller inte (om användaren inte är inloggad). Så enkelt, det tog mig 6 timmar att hitta denna metod.
