iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0

這篇會帶你一步步實作:

  1. 忘記密碼(寄送重設密碼信)
  2. 透過信件連結重設密碼
  3. 已登入狀態下的「變更密碼」

忘記密碼:寄送重設密碼信

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>
  );
}

上一篇
寄送 Firebase Email 驗證信(Email Verification)
系列文
不只是登入畫面!一起打造現代化登入系統24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言