Hướng dẫn này là phần bổ sung cho Cách thiết lập xác thực Firebase bằng ứng dụng web React . Trong phần giới thiệu của hướng dẫn đó, tôi đã lưu ý rằng Firebase cung cấp các chương trình xác thực khác ngoài xác thực Email/Mật khẩu cơ bản. Một trong những lựa chọn thay thế đó là Xác thực không cần mật khẩu .
Xác thực không cần mật khẩu là một lựa chọn hấp dẫn khi xây dựng ứng dụng. Nó đơn giản hóa trải nghiệm người dùng vì người dùng của bạn không cần phải nhớ (các) mật khẩu của họ và do đó không bao giờ phải lo lắng về việc mất chúng. Nó cũng tạo điều kiện thuận lợi cho trải nghiệm phát triển vì không cần thiết kế bất kỳ logic quản lý hoặc thu thập mật khẩu nào.
Trong hướng dẫn này, bạn sẽ xây dựng quy trình làm việc Đăng nhập/Xác nhận/Hồ sơ/Đăng xuất đơn giản để triển khai xác thực không cần mật khẩu của Firebase.
Google đặt ra nhiều giới hạn Xác thực Firebase khác nhau. Nếu bạn đang sử dụng gói Spark miễn phí, hãy lưu ý rằng bạn sẽ bị giới hạn 5 email liên kết đăng nhập mỗi ngày. Mặc dù gói Spark có thể đủ cho mục đích thử nghiệm nhưng bạn sẽ cần nâng cấp lên gói Blaze trả tiền khi sử dụng để vượt quá giới hạn này.
Trong suốt hướng dẫn này, tôi sẽ tham khảo Cách thiết lập xác thực Firebase với hướng dẫn Ứng dụng web React làm hướng dẫn tiên quyết và dự án liên quan làm dự án tiên quyết .
Để hoàn thành hướng dẫn này, bạn sẽ cần phải có:
Trong hướng dẫn tiên quyết, bạn đã tạo dự án Firebase mới để xác thực email/mật khẩu cơ bản. Bây giờ, bạn sẽ kích hoạt chính dự án đó để xác thực không cần mật khẩu. Đăng nhập vào tài khoản Firebase của bạn và nhấp vào Go to Console .
Nhấp vào dự án xác thực của bạn được liệt kê trên trang tổng quan dự án Firebase. Hướng dẫn này sử dụng tên dự án my-auth-test
.
Nhấp vào xác thực trong menu bảng điều khiển bên trái.
Nhấp vào tab Phương thức đăng nhập trong cửa sổ chính.
Từ công việc của bạn trong hướng dẫn điều kiện tiên quyết, bảng Nhà cung cấp đăng nhập phải hiển thị Email/Mật khẩu trong cột Nhà cung cấp với trạng thái Đã bật . Nhấp vào biểu tượng bút chì để mở bảng cấu hình cho nhà cung cấp Email/Mật khẩu .
Nhấp vào nút chuyển đổi để bật liên kết Email (đăng nhập không cần mật khẩu) .
Nhấp vào Lưu .
Dự án Firebase của bạn hiện đã được định cấu hình để hỗ trợ xác thực không cần mật khẩu.
Tạo một dự án React mới bằng tên ứng dụng bạn muốn. Hướng dẫn này sử dụng passwordless-auth
.
npx create-react-app passwordless-auth
Hướng dẫn này yêu cầu cài đặt 3 gói Node.js:
Cài đặt từng gói trong ba gói trên thông qua npm
:
npm install firebase
npm install react-router-dom
npm install bootstrap
firebase.js
từ Dự án tiên quyết Trong dự án tiên quyết, bạn đã tạo tệp firebase.js
sử dụng dữ liệu cấu hình dự án Firebase để tạo phiên bản của dịch vụ Xác thực Firebase. Tệp firebase.js
của bạn phải có cấu trúc sau với các giá trị cấu hình dự án Firebase của bạn :
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; const firebaseConfig = { apiKey: "AIzaSyDiUlY68W9Li_0EIkmdGdzD7nvqCT9kHnY", authDomain: "my-auth-test-fbd48.firebaseapp.com", projectId: "my-auth-test-fbd48", storageBucket: "my-auth-test-fbd48.appspot.com", messagingSenderId: "1078604952662", appId: "1:1078604952662:web:5d0b908439cfb5684ab7f7" } const app = initializeApp(firebaseConfig); const auth = getAuth(app); export { auth }
Sao chép firebase.js
vào thư mục dự án React mới của bạn.
Nếu bạn cần xem lại cấu hình dự án Firebase của mình, hãy nhấp vào biểu tượng bánh răng bên cạnh Tổng quan về dự án trong menu bảng điều khiển bên trái. Tab Chung đã được chọn. Cuộn xuống phần Ứng dụng của bạn chứa bảng Ứng dụng web . Tùy chọn npm trong bảng ứng dụng Web đã được chọn. Giá trị cấu hình dự án của bạn sẽ được liệt kê trong khối mã được hiển thị.
Ứng dụng React sẽ bao gồm 5 thành phần: App
, Layout
, Login
, Confirm
và Profile
.
App
App
xác định cấu trúc ứng dụng tổng thể, bao gồm cả định tuyến. Layout
Layout
chỉ định đánh dấu ứng dụng luôn nhất quán trên tất cả các tuyến. Login
Confirm
Confirm
khi họ nhấp vào liên kết đăng nhập. Profile
Profile
sau khi xác nhận địa chỉ email của họ.Profile
để đăng xuất khỏi tài khoản của mình. Thư mục src
cuối cùng sẽ chứa các file sau:
src |__ index.js |__ firebase.js // Copied from prerequisite project in Step 3. |__ App.js |__ Layout.jsx |__ Login.jsx |__ Confirm.jsx |__ Profile.jsx
reportWebVitals.js
setupTests.js
logo.svg
index.css
App.css
App.test.js
Sao chép index.js
từ dự án tiên quyết vào thư mục dự án mới của bạn. Hướng dẫn này sử dụng cùng một tập tin. Nếu bạn cần xây dựng lại index.js
, hãy xem Bước 5b.2 của hướng dẫn điều kiện tiên quyết hoặc sao chép khối mã bên dưới.
Sao chép Layout.jsx
từ dự án tiên quyết vào thư mục dự án mới của bạn. Hướng dẫn này sử dụng cùng một tập tin. Nếu bạn cần xây dựng lại Layout.jsx
, hãy xem Bước 5d của hướng dẫn điều kiện tiên quyết hoặc sao chép khối mã bên dưới. Theo tùy chọn, bạn có thể cập nhật văn bản dự án trong thẻ <p>
của Layout.jsx
để React With Firebase Passwordless Authentication
hoặc bất kỳ tiêu đề nào bạn thích.
Các tệp index.js
và Layout.jsx
của bạn phải như sau:
// index.js import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import "bootstrap/dist/css/bootstrap.min.css"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );
// Layout.jsx import { Outlet } from "react-router-dom"; const Layout = () => { return( <div className = "container-fluid"> <div className = "row justify-content-center mt-3"> <div className = "col-md-4 text-center"> <p className = "lead">React With Firebase Passwordless Authentication</p> </div> <Outlet /> </div> </div> ) } export default Layout
App.js
Tệp App.js
phần lớn giống như trong dự án tiên quyết, chỉ thay đổi hai dòng. Để tạo điều kiện thuận lợi cho việc xây dựng tệp, hãy sao chép App.js
từ dự án tiên quyết vào thư mục dự án mới của bạn.
Xóa dòng import
sau khỏi tệp và thay thế nó như hiển thị bên dưới:
// Delete this line: import Signup from "./Signup";
// Replace it with: import Confirm from "./Confirm";
Xóa <Route>
sau khỏi tệp và thay thế nó như hiển thị bên dưới:
// Delete this line: <Route path = "/signup" element = { <Signup></Signup> } ></Route>
// Replace it with: <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route>
Lưu App.js
.
Tệp hoàn chỉnh bây giờ sẽ như sau:
import Layout from "./Layout"; import Login from "./Login"; import Confirm from "./Confirm"; import Profile from "./Profile"; import { BrowserRouter, Routes, Route } from "react-router-dom"; const App = () => { return ( <BrowserRouter> <Routes> <Route path = "/" element = { <Layout></Layout> }> <Route index element = { <Login></Login> }></Route> <Route path = "/confirm" element = { <Confirm></Confirm> } ></Route> <Route path = "/profile" element = { <Profile></Profile> } ></Route> </Route> </Routes> </BrowserRouter> ) } export default App
Lưu ý rằng thành phần Login
một lần nữa lại là tuyến đường chính của ứng dụng giống như với dự án tiên quyết.
Login.jsx
Trong trường hợp xác thực không cần mật khẩu, rõ ràng bạn không cần bao gồm trường mật khẩu và cũng không cần quản lý trạng thái để nhập mật khẩu. Vì vậy, biểu mẫu đăng nhập chỉ cần nắm bắt địa chỉ email của người dùng.
Tạo một tệp Login.jsx
mới trong thư mục src
.
Thêm mã sau đây:
import { useState } from "react"; import { auth } from "./firebase"; import { sendSignInLinkToEmail } from "firebase/auth"; const Login = () => { const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const actionCodeSettings = { url: "http://localhost:3000/confirm", handleCodeInApp: true } const callSendSignInLinkToEmail = (e) => { e.preventDefault(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { setNotice("An email was sent to your email address. Click the link in the email to login."); }) .catch((error) => { setNotice("An error occurred when sending a login link to your email address: ", error.name); }) } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleInputEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleInputEmail" className = "form-label">Email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSendSignInLinkToEmail(e)}>Submit</button> </div> </form> </div> </div> ) }
Login.jsx
.
Khi lấy được địa chỉ email của người dùng, biểu mẫu Login.jsx
sẽ gửi email có liên kết đăng nhập đến địa chỉ của người dùng đó thông qua phương thức sendSignInLinkToEmail
của Firebase. Nếu thành công, người dùng sẽ được thông báo rằng email đã được gửi. Lưu ý rằng đối tượng actionCodeSettings
được truyền dưới dạng tham số cho phương thức sendSignInLinkToEmail
và bao gồm URL mà người dùng sẽ được chuyển đến khi họ nhấp vào liên kết đăng nhập được gửi qua email. Trong trường hợp này, URL sẽ ánh xạ tới tuyến /confirm
được chỉ định trong App.js
.
Confirm.jsx
Phương thức signInWithEmailLink
của Firebase được sử dụng để đăng nhập người dùng đã nhấp vào liên kết đăng nhập. Như bạn sẽ thấy ngay sau đây, phương thức này lấy một tham số email
và giá trị của email
phải khớp với địa chỉ email mà người dùng đã sử dụng khi đăng nhập qua biểu mẫu đăng nhập. Confirm.jsx
cung cấp cho người dùng một biểu mẫu để xác nhận địa chỉ email của họ và sau đó thử đăng nhập vào người dùng.
Tạo tệp Confirm.jsx
mới trong thư mục src
.
Thêm mã sau đây:
import { useState } from "react"; import { auth } from "./firebase"; import { isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Confirm = () => { const navigate = useNavigate(); const [email, setEmail] = useState(""); const [notice, setNotice] = useState(""); const callSignInWithEmailLink = (e) => { e.preventDefault(); if (isSignInWithEmailLink(auth, window.location.href)) { signInWithEmailLink(auth, email, window.location.href) .then(() => { navigate("/profile"); }) .catch((error) => { setNotice("An occurred during sign in: ", error.name); }) } } return( <div className = "container"> <div className = "row justify-content-center"> <form className = "col-md-4 mt-3 pt-3 pb-3"> { "" !== notice && <div className = "alert alert-warning" role = "alert"> { notice } </div> } <div className = "form-floating mb-3"> <input type = "email" className = "form-control" id = "exampleConfirmEmail" placeholder = "[email protected]" value = { email } onChange = { (e) => setEmail(e.target.value) }></input> <label htmlFor = "exampleConfirmEmail" className = "form-label">Please confirm your email address</label> </div> <div className = "d-grid"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => callSignInWithEmailLink(e)}>Confirm</button> </div> </form> </div> </div> ) } export default Confirm
Confirm.jsx
.
Phương thức isSignInWithEmailLink
trước tiên sẽ kiểm tra xem liên kết đăng nhập mà người dùng đang sử dụng có hợp lệ hay không. Nếu đúng như vậy, phương thức signInWithEmailLink
sẽ được gọi để đăng nhập người dùng. Để nhắc lại, giá trị email
được truyền cho phương thức signInWithEmailLink
phải khớp với địa chỉ email mà người dùng đã sử dụng với biểu mẫu đăng nhập. Lưu ý rằng nếu người dùng là người dùng mới (tức là đây là lần đầu tiên họ đăng nhập), Firebase sẽ tự động tạo người dùng trong cửa hàng Xác thực Firebase. Đây là một ví dụ khác về trải nghiệm đơn giản hóa được cung cấp bởi xác thực không mật khẩu: việc tạo tài khoản cho người dùng mới được xử lý tự động.
Profile.jsx
Thành phần cuối cùng mà bạn sẽ xây dựng là Profile.jsx
. Người dùng được chuyển đến thành phần này khi họ đăng nhập thành công qua Confirm.jsx
. Tuyến chào đón người dùng bằng địa chỉ email của họ và cung cấp nút để đăng xuất. Sau khi đăng xuất, người dùng được chuyển trở lại thành phần Login
.
Tạo một tệp Profile.jsx
mới trong thư mục src
.
Thêm mã sau đây:
import { auth } from "./firebase"; import { signOut } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const Profile = () => { const navigate = useNavigate(); const logoutUser = async (e) => { e.preventDefault(); await signOut(auth); navigate("/"); } return( <div className = "container"> <div className = "row justify-content-center"> <div className = "col-md-4 text-center"> <p>Welcome <em className = "text-decoration-underline">{ auth.currentUser.email }</em>. You are logged in!</p> <div className = "d-grid gap-2"> <button type = "submit" className = "btn btn-primary pt-3 pb-3" onClick = {(e) => logoutUser(e)}>Logout</button> </div> </div> </div> </div> ) } export default Profile
Profile.jsx
.Khởi động ứng dụng React:
npm start
locahost:3000
trong trình duyệt của bạn nếu trình duyệt của bạn không tự động khởi chạy. Bạn sẽ thấy biểu mẫu Login
.
Nhập email bạn muốn sử dụng để đăng nhập và nhấp vào Gửi . Nếu gửi thành công, một thông báo sẽ hiển thị rằng một email có liên kết đăng nhập đã được gửi đến địa chỉ email của bạn.
Sign in to project-1078604952662
trong đó dãy số gồm 13 chữ số biểu thị messagingSenderId
của dự án Firebase của bạn (xem Bước 3 của hướng dẫn này). Trong phần Tùy chọn bên dưới, tôi sẽ giải thích cách bạn có thể sửa đổi tên dự án Firebase của mình để hiển thị tên "thân thiện với người dùng" trong email liên kết đăng nhập. Bây giờ, hãy mở email liên kết đăng nhập và nhấp vào liên kết đăng nhập. Bạn sẽ được chuyển đến biểu mẫu Confirm
.
Nhập địa chỉ email bạn đã sử dụng khi đăng nhập vào biểu mẫu Confirm
. Nhấp vào Xác nhận . Nếu xác nhận thành công, bạn sẽ được chuyển đến trang Profile
.
Nhấp vào nút Đăng xuất trên trang Profile
để đăng xuất. Nếu đăng xuất thành công, bạn sẽ được chuyển trở lại biểu mẫu Login
.
Các bước trên nắm bắt quy trình làm việc của ứng dụng.
Bạn có thể thay đổi tên dự án của mình để các email liên kết đăng nhập do Firebase gửi hiển thị tên "thân thiện với người dùng" thay vì, chẳng hạn như project-1078604952662
. Đăng nhập vào tài khoản Firebase của bạn và nhấp vào Go to Console .
Xác thực không cần mật khẩu dường như là một lựa chọn ngày càng phổ biến của các nhà phát triển ứng dụng và điều đó cũng dễ hiểu. Ngoài lợi thế rõ ràng là loại bỏ nhu cầu quản lý mật khẩu, còn không cần xác minh email vì quá trình gửi liên kết đăng nhập tự nó là một quá trình xác minh.
Giống như dự án tiên quyết, việc triển khai ở đây là cơ bản. Bạn có thể xem xét các cải tiến đơn giản như:
Chặn/đưa vào danh sách đen các miền địa chỉ email cụ thể (tức là các miền email spam phổ biến).
Lưu trữ cục bộ địa chỉ email được người dùng nhập trên trang Login
và kiểm tra sự tồn tại của địa chỉ email trên trang Confirm
. Với phương pháp này, nếu người dùng nhấp vào liên kết đăng nhập trên cùng một thiết bị mà họ đã truy cập trang Login
, họ sẽ không cần nhập lại địa chỉ email của mình trên trang Confirm
vì địa chỉ đó sẽ được khôi phục từ bộ nhớ cục bộ. Điều này mang lại trải nghiệm người dùng mượt mà hơn nữa.
Bạn có thể tìm hiểu thêm về Xác thực không mật khẩu Firebase thông qua tài liệu chính thức .