我想在当前的身份验证实现中重定向未经身份验证的用户。例如profile.js页面仅适用于经过身份验证的用户。当前未经身份验证的用户可以访问页面profile.js。如果用户未通过身份验证,则应将其重定向到登录页面。
userContext.js
import React, { useEffect } from 'react';
import cookie from 'js-cookie';
import {firebase} from './firebase-client';
import Router from 'next/router';
export const UserContext = React.createContext();
const tokenName = 'firebaseToken';
const UserProvider = ({ children }) => {
const logOut = async () => {
await firebase
.auth()
.signOut()
.then(() => {
console.log('User logged out.');
return null
})
.catch((e) => {
console.error(e)
})
}
const emailLogin = async (email, password) => {
await firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(() => {
console.log('User logged in.');
Router.push('/')
})
.catch((err) => {
console.log(err);
});
};
const onAuthStateChange = () => {
return firebase.auth().onAuthStateChanged(async (user) => {
if (user) {
const token = await user.getIdToken();
cookie.set(tokenName, token, { expires: 14 });
} else {
cookie.remove(tokenName);
Router.push('/auth')
}
});
};
useEffect(() => {
const unsubscribe = onAuthStateChange();
return () => {
unsubscribe();
};
}, []);
return <UserContext.Provider value={{ emailLogin, logOut }}>{children}</UserContext.Provider>;
};
export default UserProvider;
api/validate.js
import admin from '../../lib/firebase-admin';
const validate = async (token) => {
const decodedToken = await admin.auth().verifyIdToken(token, true);
let userData;
const user = await admin.auth().getUser(decodedToken.uid);
admin
.database()
.ref(`projects`)
.on('value', snapshot => {
userData = { ...snapshot.val() }
})
const result = {
user: {
uid: user.uid,
email: user.email,
emailVerified: user.emailVerified,
userData: userData
},
};
return result;
};
export default async (req, res) => {
try {
const { token } = JSON.parse(req.headers.authorization || '{}');
if (!token) {
return res.status(403).send({
errorCode: 403,
message: 'Auth token missing.',
});
}
// Call the validate function above that gets the user data.
const result = await validate(token);
return res.status(200).send(result);
} catch (err) {
// Return undefined if there is no user. You may also send a different status or handle the error in any way that you wish.
console.log(err);
const result = undefined;
return res.status(200).send(result);
}
};
_app.js
import React from 'react';
import Head from 'next/head';
import App from 'next/app'
import cookies from 'next-cookies'
import UserProvider from '../lib/userContext'
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import theme from '../theme';
export default function MyApp(props) {
const { Component, pageProps, user } = props;
React.useEffect(() => {
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<React.Fragment>
<Head>
<title>My app</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
<CssBaseline />
<UserProvider>
<Component {...{...pageProps, ...user}} />
</UserProvider>
</ThemeProvider>
</React.Fragment>
);
}
MyApp.getInitialProps = async (userContext) => {
const { ctx } = userContext;
//const { res } = ctx;
const appProps = await App.getInitialProps(userContext);
const { firebaseToken } = cookies(ctx);
if (firebaseToken) {
try {
const headers = {
'Context-Type': 'application/json',
Authorization: JSON.stringify({ token: firebaseToken }),
};
const dev = process.env.NODE_ENV === 'development';
const server = dev ? 'http://localhost:3000' : 'https://firebase-app-taupe.vercel.app/';
const result = await fetch(`${server}/api/validate`, { headers }).then((res) => res.json());
return { ...result, ...appProps };
} catch (e) {
console.log(e);
}
}
return { ...appProps };
};
从仅用户页面重定向未经身份验证的用户的最佳方法是什么?