You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React与Next中登录记住我功能:实现邮箱密码自动填充

React 及 Next.js 实现「记住我」自动填充登录表单

核心逻辑

  • 登录成功且勾选「记住我」时,将邮箱(及加密后的密码)存入localStorage(持久化存储,关闭浏览器后仍保留)
  • 页面初始化时,读取localStorage中的数据,自动填充到表单状态
  • 若未勾选「记住我」,登录后清除localStorage中的对应数据

普通 React 项目实现

import { useState, useEffect } from 'react';

const LoginForm = () => {
  const [formData, setFormData] = useState({
    email: '',
    password: '',
    rememberMe: false
  });

  // 页面加载时读取本地存储
  useEffect(() => {
    const savedEmail = localStorage.getItem('rememberedEmail');
    const savedPassword = localStorage.getItem('rememberedPassword');
    if (savedEmail && savedPassword) {
      setFormData(prev => ({
        ...prev,
        email: savedEmail,
        // 生产环境需解密后赋值
        password: savedPassword,
        rememberMe: true
      }));
    }
  }, []);

  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    // 调用登录接口
    const loginSuccess = await apiLogin(formData.email, formData.password);
    
    if (loginSuccess) {
      if (formData.rememberMe) {
        // 生产环境务必加密密码后存储
        localStorage.setItem('rememberedEmail', formData.email);
        localStorage.setItem('rememberedPassword', formData.password);
      } else {
        // 清除本地存储
        localStorage.removeItem('rememberedEmail');
        localStorage.removeItem('rememberedPassword');
      }
      // 登录成功后的跳转逻辑
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleChange}
          required
        />
      </div>
      <div>
        <label>密码:</label>
        <input
          type="password"
          name="password"
          value={formData.password}
          onChange={handleChange}
          required
        />
      </div>
      <div>
        <input
          type="checkbox"
          name="rememberMe"
          checked={formData.rememberMe}
          onChange={handleChange}
        />
        <label>记住我</label>
      </div>
      <button type="submit">登录</button>
    </form>
  );
};

export default LoginForm;

Next.js 项目实现

Next.js 13+ 的 App Router 中需使用客户端组件(添加'use client'指令),因为localStorage是浏览器端 API,服务器组件无法访问:

'use client';

import { useState, useEffect } from 'react';

export default function LoginPage() {
  const [formData, setFormData] = useState({
    email: '',
    password: '',
    rememberMe: false
  });

  useEffect(() => {
    const savedEmail = localStorage.getItem('rememberedEmail');
    const savedPassword = localStorage.getItem('rememberedPassword');
    if (savedEmail && savedPassword) {
      setFormData(prev => ({
        ...prev,
        email: savedEmail,
        // 生产环境需解密
        password: savedPassword,
        rememberMe: true
      }));
    }
  }, []);

  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: type === 'checkbox' ? checked : value
    }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    // 调用后端登录接口
    const res = await fetch('/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ 
        email: formData.email, 
        password: formData.password 
      })
    });
    const data = await res.json();
    
    if (data.success) {
      if (formData.rememberMe) {
        // 生产环境加密密码后存储
        localStorage.setItem('rememberedEmail', formData.email);
        localStorage.setItem('rememberedPassword', formData.password);
      } else {
        localStorage.removeItem('rememberedEmail');
        localStorage.removeItem('rememberedPassword');
      }
      // 跳转至首页
      window.location.href = '/';
    }
  };

  return (
    <div className="login-form">
      <form onSubmit={handleSubmit}>
        <div>
          <label htmlFor="email">邮箱</label>
          <input
            id="email"
            type="email"
            name="email"
            value={formData.email}
            onChange={handleChange}
            required
          />
        </div>
        <div>
          <label htmlFor="password">密码</label>
          <input
            id="password"
            type="password"
            name="password"
            value={formData.password}
            onChange={handleChange}
            required
          />
        </div>
        <div className="remember-me">
          <input
            id="rememberMe"
            type="checkbox"
            name="rememberMe"
            checked={formData.rememberMe}
            onChange={handleChange}
          />
          <label htmlFor="rememberMe">记住我</label>
        </div>
        <button type="submit">登录</button>
      </form>
    </div>
  );
}

关键安全提示

  • 绝对禁止明文存储密码:生产环境需对密码进行加密(如使用crypto-js库的AES加密),密钥可通过后端接口获取或存在NEXT_PUBLIC_前缀的环境变量中
  • XSS风险:localStorage易被XSS攻击窃取,敏感场景建议仅存储邮箱,密码由浏览器自动填充(开启浏览器的密码管理功能),或使用HttpOnly Cookie存储登录态
  • 合规性:需在勾选「记住我」时明确告知用户存储行为,符合隐私法规要求

内容的提问来源于stack exchange,提问作者coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:10:29