前端安全:别让你的网站变成黑客的游乐场

前端安全:别让你的网站变成黑客的游乐场

毒舌时刻

这代码写得跟筛子似的,到处都是漏洞。

各位前端同行,咱们今天聊聊前端安全。别告诉我你还在忽略安全问题,那感觉就像在没有锁的房子里放贵重物品——能放,但随时可能被偷。

为什么你需要关注前端安全

最近看到一个项目,直接在前端存储用户密码,没有任何加密措施。我就想问:你是在做网站还是在做慈善?

反面教材

// 反面教材:不安全的代码 function Login() { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const handleSubmit = async (e) => { e.preventDefault(); // 直接发送密码,没有加密 const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const data = await response.json(); // 直接存储 token 在 localStorage localStorage.setItem('token', data.token); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="用户名" value={username} onChange={(e) => setUsername(e.target.value)} /> <input type="password" placeholder="密码" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">登录</button> </form> ); } export default Login; 

毒舌点评:这代码,就像在大街上裸奔,一点隐私都没有。

正确姿势

1. 密码安全

// 正确姿势:密码安全 // 1. 使用 HTTPS // 2. 密码加密传输 function Login() { const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const handleSubmit = async (e) => { e.preventDefault(); // 使用 HTTPS 传输 const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const data = await response.json(); // 使用 httpOnly cookie 存储 token // 服务端设置: res.cookie('token', token, { httpOnly: true, secure: true }); }; return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="用户名" value={username} onChange={(e) => setUsername(e.target.value)} /> <input type="password" placeholder="密码" value={password} onChange={(e) => setPassword(e.target.value)} /> <button type="submit">登录</button> </form> ); } export default Login; 

2. XSS 防护

// 正确姿势:XSS 防护 // 1. 使用 dangerouslySetInnerHTML 时要小心 // 2. 对用户输入进行转义 function CommentList({ comments }) { return ( <div> {comments.map(comment => ( <div key={comment.id}> {/* 安全的方式:直接渲染文本 */} <p>{comment.content}</p> {/* 不安全的方式 */} {/* <p dangerouslySetInnerHTML={{ __html: comment.content }} /> */} </div> ))} </div> ); } // 后端转义 // server.js app.post('/api/comments', (req, res) => { const { content } = req.body; // 转义用户输入 const escapedContent = escapeHtml(content); // 存储转义后的内容 db.insert({ content: escapedContent }); res.json({ success: true }); }); function escapeHtml(text) { return text .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#039;'); } 

3. CSRF 防护

// 正确姿势:CSRF 防护 // 1. 使用 CSRF token // 2. 验证 Origin/Referer 头 function Form() { const [csrfToken, setCsrfToken] = React.useState(''); React.useEffect(() => { // 从服务端获取 CSRF token async function getCsrfToken() { const response = await fetch('/api/csrf-token'); const data = await response.json(); setCsrfToken(data.token); } getCsrfToken(); }, []); const handleSubmit = async (e) => { e.preventDefault(); const response = await fetch('/api/submit', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ /* 表单数据 */ }) }); const data = await response.json(); console.log(data); }; return ( <form onSubmit={handleSubmit}> <input type="hidden" name="_csrf" value={csrfToken} /> {/* 表单字段 */} <button type="submit">提交</button> </form> ); } // 服务端验证 // server.js app.post('/api/submit', (req, res) => { const csrfToken = req.headers['x-csrf-token'] || req.body._csrf; if (!csrfToken || !validateCsrfToken(csrfToken)) { return res.status(403).json({ error: 'CSRF token invalid' }); } // 处理请求 res.json({ success: true }); }); 

4. 依赖安全

// 正确姿势:依赖安全 // 1. 定期更新依赖 // 2. 使用 npm audit 检查漏洞 // 3. 使用 Snyk 等工具监控 // package.json { "name": "my-app", "version": "1.0.0", "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "scripts": { "audit": "npm audit", "update": "npm update" } } // 运行命令 // npm run audit // npm run update 

毒舌点评:这才叫前端安全,让你的网站固若金汤,再也不用担心黑客攻击了。

Read more

AI提示词:零基础入门与核心概念

AI提示词:零基础入门与核心概念

AI提示词:零基础入门与核心概念 📝 本章学习目标:理解什么是提示词,掌握提示词的核心概念,建立正确的AI对话思维,为后续学习打下坚实基础。 一、什么是提示词? 1.1 提示词的定义 提示词(Prompt),简单来说,就是你发给AI的指令或问题。它是人类与人工智能沟通的桥梁,是你告诉AI"我想要什么"的方式。 想象一下,你雇佣了一位超级聪明但对你的需求一无所知的助手。这位助手知识渊博、能力强大,但它需要你清晰地告诉它要做什么。提示词就是你给这位助手的工作指令。 💡 核心认知:提示词不是简单的"提问",而是一种结构化的指令设计。好的提示词能让AI精准理解你的意图,输出高质量的结果;糟糕的提示词则会让AI"答非所问",浪费你的时间。 1.2 提示词的重要性 为什么提示词如此重要?让我们通过一个对比来说明: ❌ 糟糕的提示词: 帮我写点东西 ✅ 好的提示词: 请帮我写一篇关于&

支持LoRA和QLoRA的LLama-Factory镜像已发布,轻松节省GPU算力成本

支持LoRA和QLoRA的LLama-Factory镜像已发布,轻松节省GPU算力成本 在大模型时代,一个现实问题困扰着无数开发者:如何用有限的硬件资源微调动辄数十亿参数的语言模型?全参数微调虽然效果好,但一张A100显卡都未必扛得住。而如今,这个问题正在被彻底改写。 随着LoRA与QLoRA技术的成熟,以及LLama-Factory这类集成化框架的推出,我们已经可以在单张RTX 3090上完成7B甚至13B级别模型的高效微调——这在过去几乎是不可想象的。更重要的是,整个过程不再需要编写复杂的训练脚本,非技术人员也能通过图形界面完成定制化训练。 这一切的背后,是参数高效微调(PEFT)与量化技术的深度融合,也是开源社区对“普惠AI”的一次有力实践。 LoRA:让微调变得轻量而高效 传统微调会更新模型中所有参数,以LLaMA-7B为例,约有67亿个可训练参数,光优化器状态就可能占用超过80GB显存。这种资源消耗对于大多数个人或中小企业来说是难以承受的。 LoRA(Low-Rank Adaptation)的出现改变了这一局面。它的核心思想非常巧妙:冻结原始权重,仅引入少量可训练

基于Whisper-large-v3的多语言翻译系统开发

基于Whisper-large-v3的多语言翻译系统开发 想象一下这样的场景:一场国际线上会议正在进行,参会者来自世界各地,说着不同的语言。一位德国同事用德语发言,一位日本伙伴用日语提问,而你作为会议组织者,需要实时理解所有人的发言,并确保沟通顺畅。传统做法是雇佣多名翻译,成本高昂且响应延迟。现在,有了基于Whisper-large-v3构建的多语言翻译系统,这一切都可以自动化完成,而且成本只是传统方案的零头。 本文将带你一步步构建这样一个系统,从语音识别到文本翻译,形成一个完整的流水线。无论你是想为跨国团队开发内部工具,还是想为内容平台添加多语言字幕功能,这套方案都能为你提供一个坚实的起点。 1. 为什么选择Whisper-large-v3? 在开始动手之前,我们先聊聊为什么Whisper-large-v3是构建多语言翻译系统的理想选择。 Whisper-large-v3是OpenAI开源的语音识别模型,它最大的特点就是“多语言”和“高精度”。这个模型在超过100万小时的音频数据上训练过,支持99种语言的识别,包括英语、中文、法语、德语、日语、韩语等主流语言,甚至还能识别

从Obsidian App迁移到Obsidian.nvim:保留所有功能的无缝过渡方案

从Obsidian App迁移到Obsidian.nvim:保留所有功能的无缝过渡方案 【免费下载链接】obsidian.nvimObsidian 🤝 Neovim 项目地址: https://gitcode.com/gh_mirrors/obs/obsidian.nvim Obsidian.nvim是一款将Obsidian的强大功能与Neovim的高效编辑体验完美结合的插件。如果你是Obsidian App的忠实用户,又想体验Neovim带来的极致编辑效率,本文将为你提供一份保留所有功能的无缝迁移指南,让你轻松过渡到Obsidian.nvim的世界。 为什么选择Obsidian.nvim? Obsidian.nvim不仅继承了Obsidian App的核心功能,还融入了Neovim的强大编辑能力。它支持双向链接、标签管理、每日笔记等Obsidian的标志性功能,同时提供了Vim快捷键、代码高亮、插件扩展等Neovim特有的优势。对于习惯使用Obsidian进行知识管理,又追求高效编辑体验的用户来说,Obsidian.nvim是理想的选择。 准备工作:安装Obsidia