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
相关产品推荐
相关产品推荐

