password 密码输入
type="password" 创建一个密码输入框,用户输入的每个字符都会被替换为掩码字符(通常是圆点或星号),防止密码被旁观者看到。本节将详细讲解密码输入框的使用、密码可见性切换的实现方式,以及密码输入的安全注意事项。
前置知识
阅读本节前,建议先了解:text 文本输入
基础概念
什么是 password 输入
type="password" 与 type="text" 的行为几乎完全相同,唯一的区别是:输入的字符会被掩码隐藏显示。它支持与 text 相同的大部分属性,如 maxlength、minlength、pattern、placeholder、required 等。
<!-- text:输入内容明文显示 -->
<input type="text" name="username" placeholder="用户名">
<!-- password:输入内容以掩码显示 -->
<input type="password" name="password" placeholder="密码">password 的核心特征
| 特征 | 说明 |
|---|---|
| 显示方式 | 字符显示为掩码(圆点/星号) |
| 数据类型 | 纯文本字符串(明文传输) |
| 自动验证 | 无自动格式验证 |
| 剪贴板 | 可以复制粘贴(粘贴内容也被掩码) |
| 浏览器自动填充 | 密码管理器可能自动填充 |
语法
基本语法
<input
type="password"
name="password"
id="password"
placeholder="请输入密码"
required
minlength="8"
maxlength="64"
autocomplete="current-password"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="至少8位,包含大小写字母和数字"
>password 专用属性
type="password" 支持的属性与 type="text" 基本一致。以下是密码场景中常用的属性组合:
| 属性 | 建议值 | 说明 |
|---|---|---|
autocomplete | current-password | 当前密码(登录场景) |
autocomplete | new-password | 新密码(注册/修改密码场景) |
minlength | 8 或更大 | 最小密码长度 |
maxlength | 64 或 128 | 最大密码长度 |
pattern | 正则表达式 | 密码复杂度要求 |
required | - | 密码为必填项 |
placeholder | 提示文字 | 如"请输入密码" |
详细说明
基本使用
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>密码输入基本使用</title>
<style>
.form-group {
margin-bottom: 16px;
}
label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
input {
width: 300px;
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
input:focus {
outline: none;
border-color: #4a90d9;
box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.1);
}
</style>
</head>
<body>
<h2>用户登录</h2>
<form action="/api/login" method="post">
<div class="form-group">
<label for="username">用户名</label>
<input type="text" id="username" name="username"
placeholder="请输入用户名" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" name="password"
placeholder="请输入密码" required
autocomplete="current-password">
</div>
<button type="submit">登录</button>
</form>
</body>
</html>密码可见性切换
浏览器不会自动提供密码显示/隐藏按钮(Firefox 除外,有内置按钮)。通常需要通过 JavaScript 实现这个功能。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>密码可见性切换</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 400px;
margin: 40px auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
.password-wrapper {
position: relative;
width: 100%;
}
.password-wrapper input {
width: 100%;
padding: 10px 40px 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
.toggle-btn {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
font-size: 14px;
color: #666;
padding: 4px 8px;
}
.toggle-btn:hover {
color: #333;
}
</style>
</head>
<body>
<h2>设置密码</h2>
<form action="/api/register" method="post">
<div class="form-group">
<label for="password">密码</label>
<div class="password-wrapper">
<input type="password"
id="password"
name="password"
placeholder="请输入密码"
required
minlength="8"
autocomplete="new-password">
<!-- 切换按钮 -->
<button type="button" class="toggle-btn" onclick="togglePassword('password', this)">
显示
</button>
</div>
</div>
<div class="form-group">
<label for="confirmPassword">确认密码</label>
<div class="password-wrapper">
<input type="password"
id="confirmPassword"
name="confirm_password"
placeholder="再次输入密码"
required
minlength="8"
autocomplete="new-password">
<button type="button" class="toggle-btn" onclick="togglePassword('confirmPassword', this)">
显示
</button>
</div>
</div>
<button type="submit">注册</button>
</form>
<script>
/**
* 切换密码可见性
* @param {string} inputId - 输入框的 id
* @param {HTMLButtonElement} btn - 切换按钮元素
*/
function togglePassword(inputId, btn) {
const input = document.getElementById(inputId);
if (input.type === 'password') {
// 切换为明文显示
input.type = 'text';
btn.textContent = '隐藏';
} else {
// 切换为密码显示
input.type = 'password';
btn.textContent = '显示';
}
}
</script>
</body>
</html>使用 show-password 按钮图标
更现代的做法是使用图标来表示显示/隐藏状态:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>图标密码切换</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 400px;
margin: 40px auto;
padding: 20px;
}
.password-field {
position: relative;
margin-bottom: 20px;
}
.password-field label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
.password-field input {
width: 100%;
padding: 10px 44px 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
.eye-btn {
position: absolute;
right: 6px;
top: 32px;
background: none;
border: none;
cursor: pointer;
padding: 6px;
color: #666;
font-size: 18px;
line-height: 1;
}
.eye-btn:hover {
color: #333;
}
/* 隐藏图标和显示图标 */
.icon-eye { display: inline; }
.icon-eye-slash { display: none; }
.visible .icon-eye { display: none; }
.visible .icon-eye-slash { display: inline; }
</style>
</head>
<body>
<form action="/api/login" method="post">
<div class="password-field">
<label for="pwd">密码</label>
<input type="password" id="pwd" name="pwd"
placeholder="请输入密码" autocomplete="current-password">
<button type="button" class="eye-btn" id="toggleBtn"
aria-label="切换密码可见性">
<!-- 使用 SVG 图标 -->
<svg class="icon-eye" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
<circle cx="12" cy="12" r="3"/>
</svg>
<svg class="icon-eye-slash" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/>
<line x1="1" y1="1" x2="23" y2="23"/>
</svg>
</button>
</div>
<button type="submit">登录</button>
</form>
<script>
const toggleBtn = document.getElementById('toggleBtn');
const pwdInput = document.getElementById('pwd');
toggleBtn.addEventListener('click', function() {
const isPassword = pwdInput.type === 'password';
pwdInput.type = isPassword ? 'text' : 'password';
// 切换图标的可见性
this.classList.toggle('visible', isPassword);
// 更新无障碍标签
this.setAttribute('aria-label',
isPassword ? '隐藏密码' : '显示密码'
);
});
</script>
</body>
</html>密码强度检测
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>密码强度检测</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 400px;
margin: 40px auto;
padding: 20px;
}
.password-group {
margin-bottom: 16px;
}
.password-group label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
.password-group input {
width: 100%;
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
box-sizing: border-box;
}
/* 密码强度条 */
.strength-bar {
display: flex;
gap: 4px;
margin-top: 8px;
}
.strength-bar .bar {
flex: 1;
height: 4px;
background-color: #e0e0e0;
border-radius: 2px;
transition: background-color 0.3s;
}
.strength-text {
font-size: 12px;
margin-top: 4px;
color: #666;
}
/* 密码规则清单 */
.rules {
list-style: none;
padding: 0;
margin-top: 8px;
font-size: 13px;
}
.rules li {
padding: 2px 0;
color: #999;
}
.rules li.pass {
color: #27ae60;
}
.rules li.pass::before {
content: '✓ ';
}
.rules li.fail::before {
content: '○ ';
}
</style>
</head>
<body>
<form action="/api/set-password" method="post">
<div class="password-group">
<label for="newPwd">设置密码</label>
<input type="password" id="newPwd" name="password"
placeholder="至少8位" required minlength="8"
autocomplete="new-password">
<!-- 密码强度条 -->
<div class="strength-bar">
<div class="bar" id="bar1"></div>
<div class="bar" id="bar2"></div>
<div class="bar" id="bar3"></div>
<div class="bar" id="bar4"></div>
</div>
<div class="strength-text" id="strengthText"></div>
<!-- 密码规则 -->
<ul class="rules" id="rules">
<li id="rule-length" class="fail">至少8个字符</li>
<li id="rule-upper" class="fail">包含大写字母</li>
<li id="rule-lower" class="fail">包含小写字母</li>
<li id="rule-number" class="fail">包含数字</li>
<li id="rule-special" class="fail">包含特殊字符</li>
</ul>
</div>
</form>
<script>
const pwdInput = document.getElementById('newPwd');
const bars = [
document.getElementById('bar1'),
document.getElementById('bar2'),
document.getElementById('bar3'),
document.getElementById('bar4')
];
const strengthText = document.getElementById('strengthText');
const rules = {
length: document.getElementById('rule-length'),
upper: document.getElementById('rule-upper'),
lower: document.getElementById('rule-lower'),
number: document.getElementById('rule-number'),
special: document.getElementById('rule-special')
};
const strengthColors = ['#e74c3c', '#f39c12', '#f1c40f', '#27ae60'];
const strengthLabels = ['弱', '一般', '较强', '强'];
pwdInput.addEventListener('input', function() {
const pwd = this.value;
// 检查各项规则
const checks = {
length: pwd.length >= 8,
upper: /[A-Z]/.test(pwd),
lower: /[a-z]/.test(pwd),
number: /[0-9]/.test(pwd),
special: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(pwd)
};
// 更新规则列表样式
for (const [key, el] of Object.entries(rules)) {
el.className = checks[key] ? 'pass' : 'fail';
}
// 计算满足的规则数
const passedCount = Object.values(checks).filter(Boolean).length;
// 更新强度条
bars.forEach((bar, i) => {
if (i < passedCount) {
bar.style.backgroundColor = strengthColors[Math.min(passedCount - 1, 3)];
} else {
bar.style.backgroundColor = '#e0e0e0';
}
});
// 更新强度文字
if (pwd.length === 0) {
strengthText.textContent = '';
} else if (passedCount <= 1) {
strengthText.textContent = '密码强度:弱';
strengthText.style.color = '#e74c3c';
} else if (passedCount === 2) {
strengthText.textContent = '密码强度:一般';
strengthText.style.color = '#f39c12';
} else if (passedCount === 3) {
strengthText.textContent = '密码强度:较强';
strengthText.style.color = '#f1c40f';
} else {
strengthText.textContent = '密码强度:强';
strengthText.style.color = '#27ae60';
}
});
</script>
</body>
</html>安全注意事项
安全警告
密码输入框只是在视觉上隐藏了输入内容,它并没有对数据进行加密。以下安全要点必须了解:
1. 密码以明文传输(除非使用 HTTPS)
<!--
如果页面使用 HTTP(非 HTTPS),
密码以明文形式在网络上传输!
攻击者可以截获网络请求获取密码。
始终使用 HTTPS 保护包含密码的表单。
-->
<form action="https://example.com/login" method="post">
<input type="password" name="password">
</form>2. 密码管理器的自动填充
<!--
浏览器的密码管理器可能自动填充密码。
对于修改密码页面,使用 new-password 防止填充旧密码。
-->
<input type="password" name="password" autocomplete="new-password">3. 不要在前端限制密码字符
<!--
不推荐:限制密码只能包含字母和数字
这降低了密码的安全性
-->
<!-- <input type="password" pattern="[a-zA-Z0-9]+"> -->
<!-- 推荐:允许特殊字符,只限制长度 -->
<input type="password" minlength="8" maxlength="128">4. 密码不应出现在 URL 中
<!--
错误!GET 请求会把密码放在 URL 中
URL 会被浏览器历史、服务器日志等记录
-->
<!-- <form action="/login" method="get">
<input type="password" name="password">
</form> -->
<!-- 正确:使用 POST -->
<form action="/login" method="post">
<input type="password" name="password">
</form>实战示例
完整的修改密码表单
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>修改密码</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 450px;
margin: 40px auto;
padding: 20px;
background-color: #f5f5f5;
}
.card {
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
h2 {
text-align: center;
margin-bottom: 24px;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
.input-wrapper {
position: relative;
}
.input-wrapper input {
width: 100%;
padding: 10px 40px 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-size: 14px;
}
.toggle-btn {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
color: #666;
padding: 4px;
font-size: 13px;
}
.btn-submit {
width: 100%;
padding: 12px;
background-color: #4a90d9;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
margin-top: 8px;
}
.btn-submit:hover {
background-color: #3a7bc8;
}
</style>
</head>
<body>
<div class="card">
<h2>修改密码</h2>
<form id="changePwdForm" action="/api/change-password" method="post">
<div class="form-group">
<label for="oldPwd">当前密码</label>
<div class="input-wrapper">
<input type="password"
id="oldPwd"
name="old_password"
placeholder="请输入当前密码"
required
autocomplete="current-password">
<button type="button" class="toggle-btn"
onclick="togglePwd('oldPwd', this)">显示</button>
</div>
</div>
<div class="form-group">
<label for="newPwd">新密码</label>
<div class="input-wrapper">
<input type="password"
id="newPwd"
name="new_password"
placeholder="至少8位,包含字母和数字"
required
minlength="8"
autocomplete="new-password">
<button type="button" class="toggle-btn"
onclick="togglePwd('newPwd', this)">显示</button>
</div>
</div>
<div class="form-group">
<label for="confirmPwd">确认新密码</label>
<div class="input-wrapper">
<input type="password"
id="confirmPwd"
name="confirm_password"
placeholder="再次输入新密码"
required
minlength="8"
autocomplete="new-password">
<button type="button" class="toggle-btn"
onclick="togglePwd('confirmPwd', this)">显示</button>
</div>
</div>
<button type="submit" class="btn-submit">修改密码</button>
</form>
</div>
<script>
function togglePwd(id, btn) {
const input = document.getElementById(id);
input.type = input.type === 'password' ? 'text' : 'password';
btn.textContent = input.type === 'password' ? '显示' : '隐藏';
}
const form = document.getElementById('changePwdForm');
form.addEventListener('submit', function(e) {
e.preventDefault();
const newPwd = document.getElementById('newPwd').value;
const confirmPwd = document.getElementById('confirmPwd').value;
// 检查两次密码是否一致
if (newPwd !== confirmPwd) {
document.getElementById('confirmPwd')
.setCustomValidity('两次输入的密码不一致');
this.reportValidity();
return;
}
// 清除自定义验证
document.getElementById('confirmPwd').setCustomValidity('');
// 检查新密码不能与旧密码相同
const oldPwd = document.getElementById('oldPwd').value;
if (newPwd === oldPwd) {
document.getElementById('newPwd')
.setCustomValidity('新密码不能与当前密码相同');
this.reportValidity();
return;
}
document.getElementById('newPwd').setCustomValidity('');
// 提交表单
this.submit();
});
</script>
</body>
</html>注意事项
password 不等于加密:
type="password"只是在界面上隐藏输入内容,数据仍然是明文。安全性依赖于 HTTPS 传输和服务器端加密存储。autocomplete="off" 对密码可能无效:现代浏览器可能忽略密码字段的
autocomplete="off",仍然提供密码管理器的填充功能。使用new-password是更好的控制方式。不要用 JavaScript 限制密码字符集:允许用户使用任意字符作为密码(包括空格和特殊字符),这能提高密码强度。
密码可见性切换的隐私风险:在公共场所使用时,显示密码可能被旁人看到。切换按钮应明确提示用户注意周围环境。
浏览器自动填充密码:浏览器会在登录页面自动填充已保存的密码。如果不需要此功能,使用
autocomplete="new-password"或将字段名设为非标准名称(不推荐)。
最佳实践
使用 autocomplete token:登录页使用
current-password,注册/修改密码页使用new-password。提供密码可见性切换:帮助用户确认输入的密码是否正确,减少输入错误。
提供实时密码强度反馈:引导用户创建更强的密码。
使用 POST + HTTPS:密码表单必须使用 POST 方法,并通过 HTTPS 传输。
服务器端验证是最终防线:客户端验证只是辅助,密码的复杂度检查、是否与历史密码重复等必须在服务器端验证。
下一节
继续学习:email 邮箱输入