Appearance
实现 密码强度检测器 工具
分类:developer | 标签:密码、强度、安全、检测 实时评估密码强度,检测弱密码与常见模式,浏览器本地计算
2.1 功能说明
实时评估密码强度,检测弱密码与常见模式,浏览器本地计算
2.1.1 使用指南
使用指导
输入密码,实时评估强度并给出改进建议。所有计算在浏览器本地完成,密码不会上传。
评分维度
长度、大小写混合、数字、特殊符号、字符多样性、是否命中弱密码库或常见模式。
2.2 代码实现
2.2.1 组件结构
本工具是一个基于 Vue 3 <script setup> 语法的单文件组件(SFC),统一包裹在 ToolPageShell 组件内,由它提供页面标题、工具 ID、分类与「使用指南」插槽等通用外壳;核心业务逻辑(响应式状态、计算属性、事件处理函数)全部写在 <script setup> 中,输入/输出通过 el-input、el-button 等 Element Plus 组件与用户交互,所有数据均在浏览器本地处理,不会上传服务器。
2.2.2 核心逻辑概览
<script setup> 中定义的主要函数/方法:
formatDuration()
2.2.3 关键实现代码
以下是该工具的完整 <script setup> 实现(核心代码)。模板(<template>)与样式(<style>)已省略。
vue
import { ref, computed } from 'vue'
import { ElIcon, ElMessage } from 'element-plus'
import { Check, Close } from '@element-plus/icons-vue'
import ToolPageShell from '@/components/ToolPageShell.vue'
const pwd = ref('')
const weakList = ['123456', 'password', '12345678', 'qwerty', 'abc123', '111111', '123123', 'admin', 'letmein', 'welcome', 'password1', 'iloveyou']
const hasLower = computed(() => /[a-z]/.test(pwd.value))
const hasUpper = computed(() => /[A-Z]/.test(pwd.value))
const hasDigit = computed(() => /\d/.test(pwd.value))
const hasSymbol = computed(() => /[^A-Za-z0-9]/.test(pwd.value))
const longEnough = computed(() => pwd.value.length >= 8)
const noRepeat = computed(() => !/(.)\1\1/.test(pwd.value))
const variety = computed(() => [hasLower.value, hasUpper.value, hasDigit.value, hasSymbol.value].filter(Boolean).length)
const foundWeak = computed(() => weakList.includes(pwd.value.toLowerCase()))
const checks = computed(() => [
{ label: '至少 8 位', ok: longEnough.value },
{ label: '含小写字母', ok: hasLower.value },
{ label: '含大写字母', ok: hasUpper.value },
{ label: '含数字', ok: hasDigit.value },
{ label: '含特殊符号', ok: hasSymbol.value },
{ label: '无连续重复', ok: noRepeat.value }
])
const score = computed(() => {
if (!pwd.value) return 0
let s = 0
if (longEnough.value) s++
if (hasLower.value && hasUpper.value) s++
if (hasDigit.value && hasSymbol.value) s++
if (variety.value >= 3 && pwd.value.length >= 12) s++
if (foundWeak.value) s = 0
if (pwd.value.length > 0 && pwd.value.length < 6) s = 0
return Math.min(s, 4)
})
const levelText = computed(() => ['极弱', '弱', '中', '强', '极强'][score.value])
const color = computed(() => ['#f56c6c', '#f56c6c', '#e6a23c', '#67c23a', '#179c3c'][score.value])
const scorePct = computed(() => (score.value / 4) * 100)
const warn = computed(() => {
if (!pwd.value) return ''
if (foundWeak.value) return '该密码在常见弱密码库中,极易被破解,请立即更换。'
if (pwd.value.length < 6) return '密码过短,建议至少 12 位并混合多种字符。'
if (variety.value < 3) return '字符种类偏少,建议同时包含大小写、数字与符号。'
return ''
})
const onlineGuess = computed(() => {
// 假设在线 1000 次/秒
const pool = Math.pow(26 + 26 + 10 + 10, 1) * Math.pow(pwd.value.length || 1, 0)
const combos = Math.pow(80, Math.max(pwd.value.length, 1))
const secs = combos / 1000
return formatDuration(secs)
})
const offlineGuess = computed(() => {
const combos = Math.pow(80, Math.max(pwd.value.length, 1))
const secs = combos / 1e9
return formatDuration(secs)
})
function formatDuration(secs) {
if (!isFinite(secs) || secs <= 0) return '立即'
const u = [['年', 31536000], ['天', 86400], ['小时', 3600], ['分钟', 60], ['秒', 1]]
for (const [name, v] of u) {
if (secs >= v) return Math.floor(secs / v) + ' ' + name
}
return '< 1 秒'
}2.3 效果截图
