這篇會帶你一步步實作:
Firebase 提供 sendPasswordResetEmail()
方法,只要輸入 email,Firebase 就會寄一封「重設密碼連結」信。
import { getAuth, sendPasswordResetEmail } from "firebase/auth";
export const sendResetPasswordEmail = async (email) => {
const auth = getAuth();
try {
await sendPasswordResetEmail(auth, email, {
url: "https://your-app-domain.com/login", // 重設完成後導向頁
handleCodeInApp: true,
});
console.log("重設密碼信已寄出");
} catch (error) {
console.error("無法寄出重設密碼信:", error.message);
throw error;
}
};
import React, { useState } from "react";
import { sendResetPasswordEmail } from "../firebase/authService";
export default function ForgotPasswordPage() {
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
try {
await sendResetPasswordEmail(email);
setMessage("重設密碼信已寄出,請至信箱確認。");
} catch (err) {
setMessage(`錯誤:${err.message}`);
}
};
return (
<div className="p-4 max-w-md mx-auto">
<h2 className="text-xl font-bold mb-2">忘記密碼</h2>
<form onSubmit={handleSubmit} className="space-y-3">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="輸入註冊時的 Email"
className="w-full p-2 border rounded"
/>
<button
type="submit"
className="w-full bg-blue-500 text-white py-2 rounded"
>
寄送重設密碼信
</button>
</form>
{message && <p className="mt-3 text-sm text-gray-600">{message}</p>}
</div>
);
}
信件內的連結長這樣:
https://your-app-domain.com/__/auth/action?mode=resetPassword&oobCode=XXXXXX
若你設定 handleCodeInApp: true
,
可以讓使用者進入自訂頁 /reset-password?oobCode=XXXXXX
,
再輸入新密碼。
實作(重設密碼頁):
import { getAuth, confirmPasswordReset } from "firebase/auth";
import { useSearchParams } from "react-router-dom";
import { useState } from "react";
export default function ResetPasswordPage() {
const [params] = useSearchParams();
const oobCode = params.get("oobCode");
const [newPassword, setNewPassword] = useState("");
const [message, setMessage] = useState("");
const handleReset = async (e) => {
e.preventDefault();
const auth = getAuth();
try {
await confirmPasswordReset(auth, oobCode, newPassword);
setMessage("✅ 密碼重設成功!請重新登入。");
} catch (err) {
setMessage(`❌ 重設失敗:${err.message}`);
}
};
return (
<div className="p-4 max-w-md mx-auto">
<h2 className="text-xl font-bold mb-2">重設密碼</h2>
<form onSubmit={handleReset} className="space-y-3">
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
placeholder="輸入新密碼"
className="w-full p-2 border rounded"
/>
<button
type="submit"
className="w-full bg-green-500 text-white py-2 rounded"
>
重設密碼
</button>
</form>
{message && <p className="mt-3 text-sm text-gray-600">{message}</p>}
</div>
);
}
當使用者已登入時,可以用 updatePassword()
直接修改。
import { getAuth, updatePassword } from "firebase/auth";
export const updateUserPassword = async (newPassword) => {
const auth = getAuth();
const user = auth.currentUser;
if (!user) throw new Error("尚未登入");
try {
await updatePassword(user, newPassword);
console.log("密碼已更新");
} catch (error) {
console.error("密碼更新失敗:", error.message);
throw error;
}
};
搭配 React 表單使用:
import React, { useState } from "react";
import { updateUserPassword } from "../firebase/authService";
export default function ChangePassword() {
const [password, setPassword] = useState("");
const [message, setMessage] = useState("");
const handleChange = async (e) => {
e.preventDefault();
try {
await updateUserPassword(password);
setMessage("密碼修改成功!");
} catch (err) {
setMessage(`錯誤:${err.message}`);
}
};
return (
<div className="p-4 max-w-md mx-auto">
<h2 className="text-xl font-bold mb-2">變更密碼</h2>
<form onSubmit={handleChange} className="space-y-3">
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="新密碼"
className="w-full p-2 border rounded"
/>
<button
type="submit"
className="w-full bg-yellow-500 text-white py-2 rounded"
>
更新密碼
</button>
</form>
{message && <p className="mt-3 text-sm text-gray-600">{message}</p>}
</div>
);
}