В этой статье мы создадим логин пользователя, используя Next.js с перехватчиками React. И мы защитим наше приложение с помощью функции аутентификации Firebase, которая позволяет только авторизованным пользователям получать доступ к частной странице.
Список моментов, на которых мы остановимся в этой статье:
- Настройка Next.js
- Компонент React
- Реагировать на крючок
- Аутентификация Firebase
- Сторонняя аутентификация с Google
Примечание. Для этого в нашей системе должны быть установлены Node.js и npm
Настройка Next.js
При создании проекта Next.js нам необходимо установить модуль create-next-app
, который обеспечивает начальную настройку и настройку по умолчанию. Установите create-next-app
командой:
npm install -g create-next-app
После завершения установки запустите проект Next.js в вашем локальном каталоге, где нам нужно создать проект, с помощью команды:
npx create-next-app next-login-firebase
После завершения установки переходим в нашу созданную папку:
cd next-login-firebase
Теперь мы закончили настройку нашего проекта Next.js.
Следующим шагом будет установка пакета Firebase и react-firebaseui.
npm i firebase react-firebaseui --save
Конфигурация Firebase для аутентификации
Firebase помогает нам с безопасным входом в систему, предоставляя методы мульти-аутентификации, такие как адрес электронной почты / пароль, Google, Facebook, Twitter и т. Д.
Перейдите на https://firebase.google.com/ и войдите со своими учетными данными.
После успешного входа в консоль Firebase мы создадим наш проект, нажав кнопку «Добавить проект», заполните форму имени проекта и следуйте инструкциям мастера:
Чтобы интегрировать наш проект Firebase в наш проект Next.js, перейдите в настройки проекта и найдите «Установка и конфигурация SDK», выберите радио «Конфигурация». Нам нужно будет скопировать фрагмент, который нужно добавить в код нашего проекта.
После создания проекта нажмите «Аутентификация» в левой части. Мы включим аутентификацию провайдера с помощью электронной почты / пароля и Google:
Написать код
В корневой папке создайте новый файл config.js с приведенным ниже кодом и сохраните его.
import firebase from 'firebase/app'; | |
import 'firebase/auth'; | |
const firebaseConfig = { | |
apiKey: "AIzaSyAXXXXXXX", | |
authDomain: "next-login-firebase.firebaseapp.com", | |
projectId: "next-login-firebase", | |
storageBucket: "next-login-firebase.appspot.com", | |
messagingSenderId: "86849XXXXX", | |
appId: "1:868XXXXXXXX:web:e3c06XXXXXXXXXXXX" | |
}; | |
export default function initFirebase() { | |
if (!firebase.apps.length) { | |
firebase.initializeApp(firebaseConfig); | |
} | |
} |
Откройте файл pages / index.js и отредактируйте с помощью приведенного ниже кода.
const Home = () => { | |
return ( | |
<div > | |
<div>Public</div> | |
<div><a href="/private">Go to Private</a></div> | |
</div> | |
) | |
} | |
export default Home; |
Для следующего шага установите пакет «js-cookie» командой:
npm i js-cookie
Создайте новый файл auth / userCookie.js, напишите следующий код:
Затем мы должны создать auth / useUser.js для обработки состояния пользователя, напишите следующий код:
import { useEffect, useState } from 'react'; | |
import { useRouter } from 'next/router'; | |
import firebase from 'firebase/app'; | |
import 'firebase/auth'; | |
import initFirebase from '../config'; | |
import { | |
removeUserCookie, | |
setUserCookie, | |
getUserFromCookie | |
} from './userCookie'; | |
initFirebase(); | |
export const mapUserData = async user => { | |
const { uid, email } = user; | |
const token = await user.getIdToken(true); | |
return { | |
id: uid, | |
email, | |
token | |
}; | |
}; | |
const useUser = () => { | |
const [user, setUser] = useState(); | |
const router = useRouter(); | |
const logout = async () => { | |
return firebase | |
.auth() | |
.signOut() | |
.then(() => { | |
router.push('/'); | |
}) | |
.catch(e => { | |
console.error(e); | |
}); | |
}; | |
useEffect(() => { | |
const cancelAuthListener = firebase | |
.auth() | |
.onIdTokenChanged(async userToken => { | |
if (userToken) { | |
const userData = await mapUserData(userToken); | |
setUserCookie(userData); | |
setUser(userData); | |
} else { | |
removeUserCookie(); | |
setUser(); | |
} | |
}); | |
const userFromCookie = getUserFromCookie(); | |
if (!userFromCookie) { | |
return; | |
} | |
setUser(userFromCookie); | |
return () => cancelAuthListener; | |
}, []); | |
return { user, logout }; | |
}; | |
export { useUser }; |
Создайте файл с именем «auth / withAuth.js» для обработки изменения статуса авторизации и перенаправления на подписывающие страницы:
import React, { useEffect } from 'react'; | |
import router from 'next/router'; | |
import firebase from 'firebase/app'; | |
import 'firebase/auth'; | |
import initFirebase from '../config'; | |
initFirebase(); | |
const auth = firebase.auth(); | |
const withAuth = Component => props => { | |
useEffect(() => { | |
auth.onAuthStateChanged(authUser => { | |
if (!authUser) { | |
router.push('/signin'); | |
} | |
}); | |
}, []); | |
return ( | |
<div> | |
<Component {...props} /> | |
</div> | |
) | |
}; | |
export default withAuth; |
Создайте новую частную страницу с именем «pages / private.js», эта страница будет отображать электронную почту и кнопку выхода, если пользователь входит в систему.
import withAuth from '../auth/withAuth'; | |
import { useUser } from '../auth/useUser'; | |
const Private = () => { | |
const { user, logout } = useUser(); | |
return ( | |
<div > | |
<div>Private</div> | |
{ | |
user?.email && | |
<div> | |
<div>Email: {user.email}</div> | |
<button onClick={() => logout()}>Logout</button> | |
</div> | |
} | |
</div> | |
) | |
} | |
export default withAuth(Private); | |
На последнем этапе создайте новый файл «pages / signin.js» для визуализации канала входа. Это пример использования «react-firebaseui».
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth'; | |
import firebase from 'firebase/app'; | |
import 'firebase/auth'; | |
import initFirebase from '../config'; | |
import { setUserCookie } from '../auth/userCookie'; | |
import { mapUserData } from '../auth/useUser'; | |
initFirebase(); | |
const firebaseAuthConfig = ({ signInSuccessUrl }) => ({ | |
signInFlow: 'popup', | |
signInOptions: [ | |
{ | |
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID, | |
requireDisplayName: false | |
}, | |
firebase.auth.GoogleAuthProvider.PROVIDER_ID, | |
], | |
signInSuccessUrl, | |
credentialHelper: 'none', | |
callbacks: { | |
signInSuccessWithAuthResult: async ({ user }, redirectUrl) => { | |
const userData = await mapUserData(user); | |
setUserCookie(userData); | |
} | |
} | |
}); | |
const FirebaseAuth = () => { | |
const signInSuccessUrl = "/private" | |
return ( | |
<div> | |
<StyledFirebaseAuth | |
uiConfig={firebaseAuthConfig({ signInSuccessUrl })} | |
firebaseAuth={firebase.auth()} | |
signInSuccessUrl={signInSuccessUrl} | |
/> | |
</div> | |
); | |
}; | |
export default FirebaseAuth; |
Наш код:
Больше контента на plainenglish.io