news 2026/7/26 4:43:13

不靠框架、不联网:用 60 行代码写一个离线密码生成器(单文件 Web 工具实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
不靠框架、不联网:用 60 行代码写一个离线密码生成器(单文件 Web 工具实战)

一、先说痛点

想临时生成个密码,你大概会搜一个「在线密码生成器」,把需求交给它。但想一想:你刚生成的口令,明文是不是已经落在了对方的服务器日志里?

更别提那些页面:先弹三个广告,再偷偷引一段第三方脚本,最后还顺手埋个埋点。工具越来越多,但它们离你的机器、离你的数据,越来越远。

能不能反过来——自己写一个,数据不出本机,断网也能跑?这一篇就带你从零做一个:一个离线密码 / 口令生成器,支持长度、字符规则、强度提示,纯前端、零依赖,最后整个东西就是一个.html文件,双击即用。

二、目标:一个能塞进 U 盘的工具

我们要交付的东西很具体:

  • 选长度(6–40 位)、选字符集(大写 / 小写 / 数字 / 符号);
  • 点一下生成,实时显示「熵强度」;
  • 一键复制,并记住你上次的长度偏好;
  • 不引任何 CDN、框架、字体不联网、不上传;存成一个.html就能发给同事。

读完你手里就有一个能用的工具,而它的全部代码,大约 60 行。

三、单文件工具长什么样

「单文件」不是噱头,而是把三件事装进一个文件:结构(HTML)+ 样式(CSS)+ 逻辑(JS)。最小骨架长这样:

<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <style> /* 样式写这里,不引外部 css */ </style> </head> <body> <!-- 结构写这里 --> <script> /* 逻辑写这里,不引外部 js */ </script> </body> </html>

三个要点:① 用系统字体栈(system-ui, "Microsoft YaHei", sans-serif),不下载字体;② 所有计算在浏览器本地完成,没有fetch到任何后端;③ 状态用localStorage留在本地。这就是「单文件 · 零依赖 · 本地优先」三条铁律的来历。

四、实战:60 行写出密码生成器

下面给出完整可复制的单文件。把它整段保存成password.html,双击就能用。

<!doctype html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>离线密码生成器</title> <style> :root { --bg:#0A0A0B; --card:#141417; --line:rgba(255,255,255,.08); --accent:#5E6AD2; --muted:#A1A1AA; } * { box-sizing:border-box; } body { margin:0; font:15px/1.6 system-ui,-apple-system,"Segoe UI",Roboto,"Microsoft YaHei",sans-serif; background:var(--bg); color:#fff; display:flex; justify-content:center; padding:32px 16px; } .app { width:100%; max-width:420px; background:var(--card); border:1px solid var(--line); border-radius:14px; padding:20px; } h1 { font-size:18px; margin:0 0 16px; } .out { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:16px; word-break:break-all; background:#0A0A0B; border:1px solid var(--line); border-radius:8px; padding:12px; min-height:48px; } button { background:var(--accent); color:#fff; border:0; border-radius:8px; padding:10px 14px; cursor:pointer; font-size:14px; } button.ghost { background:transparent; border:1px solid var(--line); color:var(--muted); } input[type=range]{ flex:1; } label.chk { display:flex; align-items:center; gap:6px; font-size:14px; color:var(--muted); } .meta { display:flex; justify-content:space-between; color:var(--muted); font-size:13px; margin-top:6px; } .bar { height:6px; border-radius:3px; background:#222; overflow:hidden; margin-top:8px; } .bar > i { display:block; height:100%; width:0; background:var(--accent); transition:width .2s; } </style> </head> <body> <div class="app"> <h1>🔐 离线密码生成器</h1> <div class="out" id="out" aria-live="polite">点击生成</div> <div class="bar"><i id="bar"></i></div> <div class="meta"><span id="bits">强度:—</span><span id="lenLabel">16 位</span></div> <div class="row" style="display:flex;align-items:center;gap:10px;margin:10px 0"> <span>长度</span> <input type="range" id="len" min="6" max="40" value="16"> </div> <div class="row" style="display:flex;flex-wrap:wrap;gap:10px;margin:10px 0"> <label class="chk"><input type="checkbox" id="up" checked> 大写</label> <label class="chk"><input type="checkbox" id="lo" checked> 小写</label> <label class="chk"><input type="checkbox" id="dg" checked> 数字</label> <label class="chk"><input type="checkbox" id="sy" checked> 符号</label> </div> <div class="row" style="display:flex;gap:10px;margin:10px 0"> <button id="gen">生成</button> <button id="copy" class="ghost">复制</button> </div> </div> <script> const $ = id => document.getElementById(id); const SETS = { up: "ABCDEFGHJKLMNPQRSTUVWXYZ", lo: "abcdefghijkmnopqrstuvwxyz", dg: "23456789", sy: "!@#$%^&()-_=+[]{}" }; // 用密码学安全随机数,而不是 Math.random() function randInt(n){ const a = new Uint32Array(1); crypto.getRandomValues(a); return a[0] % n; } function gen(){ const len = +$("len").value; let pool = ""; for (const k in SETS) if ($(k).checked) pool += SETS[k]; if (!pool) { $("out").textContent = "至少选一种字符"; return; } let s = ""; for (let i=0;i<len;i++) s += pool[randInt(pool.length)]; $("out").textContent = s; const bits = Math.round(len * Math.log2(pool.length)); // 熵估算 $("bits").textContent = "强度:" + bits + " bits"; $("bar").style.width = Math.min(100, bits/64100) + "%"; try { localStorage.setItem("pw.len", len); } catch(e){} } // 复制:优先用剪贴板 API,file:// 下回退到 execCommand function copy(){ const t = $("out").textContent; if (navigator.clipboard && window.isSecureContext) navigator.clipboard.writeText(t); else { const ta=document.createElement("textarea"); ta.value=t; document.body.appendChild(ta); ta.select(); try{document.execCommand("copy");}catch(e){} document.body.removeChild(ta); } } $("len").oninput = () => $("lenLabel").textContent = $("len").value + " 位"; $("gen").onclick = gen; $("copy").onclick = copy; const saved = +localStorage.getItem("pw.len"); if (saved) $("len").value = saved; gen(); </script> </body> </html>

这段代码里,有三个值得记住的点

1)随机性要用crypto.getRandomValues,别用Math.random()后者只是伪随机、可被预测,拿来做口令等于没加密。crypto走的是浏览器的密码学安全随机源,离线也能用。

2)强度按「熵」估算,而不是按「看起来乱不乱」。一行公式:bits = 长度 × log2(字符池大小)。16 位、含四类字符大约 90+ bits,远超够用线(64 bits 我设成进度条满格)。这比「感觉挺复杂」科学得多。

3)偏好用localStorage留本地。你下次打开还是上次的长度——但它只存在你这台机器上,不会回传任何服务器。

五、让它真正「工具化」:离线优先三铁律

把上面的思路抽出来,就是做单文件工具的三条纪律:

  • 单文件:整个工具一个.html,可下载、可邮件、可丢 U 盘;
  • 零依赖:不引任何外部 CDN / 框架 / 字体,断网照跑;
  • 本地优先:数据不出本机,没有后端、没有埋点、没有账号。

再加两个小习惯会更「专业」:用prefers-reduced-motion尊重系统的减弱动效设置;把视觉统一成一套克制的中性暗色(比如上面用的#0A0A0B画布 +#5E6AD2靛蓝强调色)。

六、收尾

到这里,你已经从零写出一个能用的单文件工具了——它不依赖任何库,断网可用,口令明文只活在你自己的浏览器里。

如果你不想自己写、想直接白嫖:nano-tools 矩阵里这个密码生成器的完整版叫PassForge,连同另外 42 款同类单文件工具(白板、JSON、哈希、正则、色彩、无障碍……)都开源在 GitHub,挑一个双击html就能用。

留个思考题:如果把这个骨架换成「UUID 生成器」「Base64 编解码」或者「JSON 格式化」,改动其实不过十几行——你最想把它改造成什么?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/26 4:42:13

C++迭代器实现指南:从概念到实战,打造STL兼容容器

1. 项目概述&#xff1a;为什么我们需要迭代器&#xff1f;在C的世界里&#xff0c;尤其是当你开始接触标准模板库&#xff08;STL&#xff09;时&#xff0c;“迭代器”这个词会高频出现。很多初学者&#xff0c;包括当年的我&#xff0c;都会有一个疑问&#xff1a;数组我可以…

作者头像 李华
网站建设 2026/7/26 4:41:43

3分钟掌握:BetterNCM安装器的完整使用指南

3分钟掌握&#xff1a;BetterNCM安装器的完整使用指南 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer BetterNCM安装器是一款专为PC版网易云音乐设计的插件管理器&#xff0c;通过一键…

作者头像 李华
网站建设 2026/7/26 4:41:42

Unity3D视差映射实现地裂效果:原理、实现与优化

1. 项目概述与核心思路拆解最近在做一个末日生存题材的小项目&#xff0c;场景里需要一种地面突然崩裂、碎石飞溅的震撼效果。如果只是简单播放一个预制动画&#xff0c;或者用粒子系统模拟&#xff0c;总觉得差点意思&#xff0c;缺乏那种随着视角移动而产生的深度感和真实感。…

作者头像 李华
网站建设 2026/7/26 4:41:31

Transformer注意力机制原理与17种工程优化实践

1. 注意力机制的本质与起源2017年那篇划时代的论文《Attention Is All You Need》彻底改变了自然语言处理的游戏规则。当时我在实验室第一次复现Transformer模型时&#xff0c;最让我震撼的不是复杂的架构&#xff0c;而是其中那个看似简单的注意力计算模块——它用几行矩阵运算…

作者头像 李华
网站建设 2026/7/26 4:39:19

基于YOLOv11的滑坡灾害实时检测系统开发实践

1. 项目背景与核心价值滑坡灾害是全球范围内最具破坏力的自然灾害之一。根据国际地质灾害防治协会统计&#xff0c;每年因滑坡造成的直接经济损失超过百亿美元。传统的人工巡查方式不仅效率低下&#xff0c;而且在高风险区域存在严重的安全隐患。我们团队开发的这套基于YOLOv11…

作者头像 李华
网站建设 2026/7/26 4:38:38

3步完成Photon光影包安装:免费提升Minecraft画质的终极解决方案

3步完成Photon光影包安装&#xff1a;免费提升Minecraft画质的终极解决方案 【免费下载链接】photon A gameplay-focused shader pack for Minecraft 项目地址: https://gitcode.com/gh_mirrors/photon3/photon Photon光影包是一款专注于游戏体验的Minecraft光影解决方案…

作者头像 李华