验证码(Verification Code)浅说
验证码(Verification Code)是一种用于确认用户身份或操作有效性的安全机制。通常情况下,验证码是一串由数字、字母或符号组成的随机生成的字符串,用户需要输入正确的验证码才能继续进行操作。
涉及重要资产、高风险操作、特权认证的场景,都需要最严格的验证码防护,以保护系统、交易和账户的安全。适当的验证码设计,可以大幅降低系统风险。
验证码的作用是用于验证用户身份,防止恶意破解密码、刷票、论坛灌水、刷页。验证码通常用于注册账户、登录、重置密码等操作中,帮助确保用户的安全和隐私。
验证码设计的核心原则在于确保用户友好性和安全性之间的平衡。
对于网站而言, 验证码的生成通常在服务器端完成, 而验证过程可以在前端和后端都进行。具体来说:
生成验证码: 服务器端生成验证码图像或字符串, 并将其存储在服务器端 (如 Session 或内存缓存中), 以便后续进行验证。这样可以避免客户端预测验证码的风险。
验证验证码: 可以分两步进行。首先在前端进行初步验证, 检查用户输入是否符合基本要求(如长度、格式等), 然后再将用户输入提交到服务器端与存储的验证码进行比对。服务器端验证是必须的, 因为前端验证可以被绕过。
验证码的种类有很多种,常见的包括:
图片验证码:要求用户识别并输入图片中的文字或数字。
短信验证码:通过短信发送给用户的一次性验证码。
邮件验证码:通过电子邮件发送给用户的一次性验证码。
语音验证码:通过电话语音播报给用户的一次性验证码。
滑块验证码:要求用户拖动滑块完成验证。
点选验证码:要求用户在图片中点选特定区域完成验证。
数学验证码:要求用户计算数学题目并输入答案完成验证。
数字验证码:这种验证码通常是由系统随机生成的一组数字,用户需要正确输入这些数字来完成验证。数字验证码常见于短信验证码,通过短信的方式发送给用户。
下面是数字验证码简化示例,使用了纯客户端 JavaScript 生成和验证验证码,请注意,这种做法存在明显的安全隐患,因为攻击者可以很容易地查看和修改前端代码,从而绕过验证码校验。此例的目的是给出一种思路演示。
先看运行效果:
源码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>验证码生成及校验</title>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #fff;
}
.Box{
margin: 100px auto 0;
text-align: center;
}
.box {
width: 300px;
color: #fff;
background-color: rgba(0, 0, 0, 0.5);
margin: auto;
text-align: center;
}
.boxCode {
width: 300px;
background-color: rgba(0, 0, 0, 0.5);
margin: auto;
}
.code {
color: red;
font-size: 30px;
}
</style>
</head>
<body>
<div class="Box">
<div class="boxCode">
<span class="code" id="code"></span>
<a href="" id="linkbt">看不清换一张</a>
</div>
<div class="box">
<label for="inputCode">验证码:</label>
<input type="text" id="inputCode">
<input type="button" id="Button1" value="确定">
</div>
</div>
<script>
'user strict';
function getCode(){
var arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
var str = '';
for (let i = 0; i < 6; ++i) {
//取0到9
let num = Math.round(Math.random() * (9 - 0) + 0);//得到0-9的一个随机数
str += arr[num];//拼接字符串
}
return str;
}
window.onload=function(){
let res=getCode();
document.getElementById("code").innerText=res;
document.getElementById("linkbt").onclick=function(){
document.getElementById("code").innerText=res;
}
document.getElementById('Button1').onclick=function(){
let code=document.getElementById('code').innerText;
let inputCode=document.getElementById('inputCode').value;
//console.log(code);
//console.log(inputCode);
if(code!=inputCode){
alert('输入错误!');
//document.getElementById('inputCode').value='';
return false;
}else{
//location.href='https://www.baidu.com/';
alert('通过验证!');
}
}
}
</script>
</body>
</html>
把以上内容用记事本打开,复制进去。然后保存为.html文件。然后双击它,就可用浏览器打开试验了。
这个示例,纯客户端的验证码方式安全性较低,仅依赖这种前端验证码很容易被攻击者绕过。需要进行改进的地方:
验证码的生成应该放在服务器端完成, 而不是在前端生成。
验证过程不应该完全依赖前端, 必须要在服务器端进行验证码的比对和校验。
验证码应该在一定时间后自动失效, 并且每次请求时都重新生成, 以防止重放攻击。
可以考虑对验证码图像进行扭曲、添加噪点等操作, 增加机器识别的难度。
对于重要的安全操作, 除了验证码之外, 还可以增加其他身份验证措施, 如手机短信验证码等。
关于这些,涉及到服务器端程序的设计和部署,前后端交互等比较麻烦,在此就就不多说了。