React-Ionic应用程序中使用Firebase身份验证上下文的受保护路由

webghufk  于 2022-12-08  发布在  Ionic
关注(0)|答案(1)|浏览(157)

I'm trying to set up a context for Firebase authentication in a React-Ionic app with some protected routes which shouldn't be accessible without being authenticated. So far it kinda works, but not completely. I can log in with no problems and navigate the pages with protected routes, but as soon as I refresh the page, it takes me back to the login page as if I weren't authenticated.
I'm pretty sure I'm messing things up somewhere but haven't been able to detect where (it's actually possible that the whole thing is wrongly implemented, as I'm quite new to this and still learning).
This is how my files look so far (without imports and stuff, just the core part):

App.tsx:

const App: React.FC = () => {

  const authContext = useContext(AuthContext);

  useEffect(() => {
    console.log(authContext) **//**
  }, [])  

  return (
    <IonApp>
      <IonReactRouter>
        <IonRouterOutlet>
          <Route exact path="/" component={PageLogin} />
          <ProtectedRoute path="/secure/home" component={PageHome} isAuthenticated={authContext.authenticated!}/>
          <ProtectedRoute path="/secure/lot/:lotId" component={PageLotOverview} isAuthenticated={authContext.authenticated!}/>
          <ProtectedRoute path="/secure/shipment/:shipmentId" component={PageShipmentOverview} isAuthenticated={authContext.authenticated!}/>
        </IonRouterOutlet>
      </IonReactRouter>
    </IonApp>
  )
}

AuthProvider.tsx:

export const AuthContext = React.createContext<Partial<ContextProps>>({});

export const AuthProvider = ({ children }: any) => {

  const [user, setUser] = useState(null as firebase.User | null);
  const [loadingAuthState, setLoadingAuthState] = useState(true);

  useEffect(() => {
    firebase.auth().onAuthStateChanged((user: any) => {
      setUser(user);
      setLoadingAuthState(false);
    });
  }, []);

  return (
    <AuthContext.Provider
      value={{
        user,
        authenticated: user !== null,
        setUser,
        loadingAuthState
      }}>
      {children}
    </AuthContext.Provider>
  );
}

ProtectedRoute.tsx:

interface ProtectedRouteProps extends RouteProps {
  component: React.ComponentType<any>;
  path: string;
  isAuthenticated: boolean
}

export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ component: Component, path, isAuthenticated }) => {

  useEffect(() => {
    console.log("from protected ROUTE", isAuthenticated)
  }, [])

return (
    <Route path={path} render={() => isAuthenticated ? <Component /> : <Redirect to="/" />} />
  );
};

index.tsx:

ReactDOM.render(
  <AuthProvider>
    <App />
  </AuthProvider>
  , document.getElementById('root'));

Please let me know if I can provide more useful information. Thanks in advance for your help.

wgxvkvu9

wgxvkvu91#

Number 1: Every One are still Learning.
Number 2: There is a very simple solution for this which I personally use (works fine). You can use something called 'session storage' facility.
As soon as you get the user data from Firebase do this :

// When login is successful

window.sessionStorage.setItem('isLogged', 'true'); 

// This will create a variable with value *true* that 
can be accessed from any page within your website

Session Storage is like a local database that can store any number of values you want to save and don't get erased on refresh. However it is just temporary and will get erased when the user closes the browser window.
Now at every protected routes you can do this.

useEffect(() => {
  if(window.sessionStorage.getItem('isLogged') == 'false')
  {
    window.location.href = '/login' // send the user to login page
  }
}, [])

Pro Tip:

Use can use this mechanism to implement 'Remember Me' option for whatever you are developing. In that case you may have to use LocalStorage which is similar to sessionStorage but it won't erase the data even when the user closes the browser window.
And again when the user visits your page, it will automatically redirect the user to the main page without logging in (if you create a useEffect to check that).
Another thing : Both localStorage and sessionStorage are different for different user. The values stored in my browser's localStorage or sessionStorage will not be visible to you or anyone for that matter except me.
That's it

相关问题