验证码组件 Yverifycode

关键字: 验证码, js, javascript, 校验, code,

本文将介绍一种基于js实现的一款验证码生成校验组件,
验证码输入忽略大小写
Yverifycode
注意: 如果对安全性要求高的应用不建议采用此组件, 无法抵御脚本攻击

Yverifycode 使用

html 标签元素

使用Yverifycode 时需要绑定三个 html 元素的 id 属性

  • 容纳验证码图片的容器, 例如:下面例子中的 #code-win, 容器的容器的尺寸决定了验证码图片的尺寸, 该元素是必须的
  • 更换验证码的按钮, 例如: 下面例子中的“换一张”, 此按钮是用于更换验证码图片的, 该元素不是必须的,也可以调用 Yverifycode.reset 方法实现
  • 验证码输入框, 例如: 下面例子中的 #code-input, 用于输入验证码, 该元素是必须的
1
2
3
4
5
6
7
<div id="for-code" class="for-code">
<div id="code-win" class="code-win"></div>
<input type="button" id="code-reset" value="换一张">
<br>
<input type="text" id="code-input"> <br>
<input type="button" id="code-verify" value="确定">
</div>

组件调用

1、引入Yverifycode 在 html 文件或以模块化方式在 js 文件中引入

2、初始化 Yverifycode 初始化参数以对象的形式传入,参数如下:

  • input: 对应验证码输入框的 id 属性值, 必填, 类型 string
  • container: 验证码图片对应容器(元素) id 属性值, 必填, 类型 string
  • reset: 更新验证码元素 id 属性值, 非必填, 类型 string
  • length: 验证码位数, 非必填, 类型 number, 默认值 4
  • width: 验证码初始化显示宽度, 非必填, 类型 number, 默认 100(px)
  • bgColor: 验证码图片背景颜色, 非必填, 类型 16色值(例如:#ff0000), 默认白色
  • bgImg: 验证码图片背景图片: 非必填, 类型 图片地址(sting), 使用优先级高于背景颜色, 即同时设置 bgColor 和 bgImg: 只有 bgImg 生效

3、获取验证结果 调用 Yverifycode 的 verify 方法获取校验结果,如果返回结果为 true, 表示校验通过, 为 false 校验失败

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//配置初始化参数
let verOpt = {
input: 'code-input',
container: 'code-win',
reset: 'code-reset',
length: 6,
bgColor: '#AEEEEE',
bgImg: '/static/images/default.jpg'
}
//实例化 Yverifycode
let yVerifycode = new Yverifycode(verOpt)
//调用 reset 方法 重置验证码
// $('#code-reset').click(() => {
// yVerifycode.reset()
// })
//调用 verify 方法 获取校验结果
$('#code-verify').click(() => {
let state = yVerifycode.verify()
if(state) {
alert('Pass')
} else {
alert('Failed')
}
})

Yverifycode 源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/**
* author: feifeiyu
* version: 1.3
* Yverifycode is a verification code component
* @param input //verification code input Dom id, not null
* @param container //verification code image container Dom id, not null
* @param reset //verification code reset Dom id
* @param length //verification code length, default 4
* @param bgColor //verification code container background color,
* @param bgImg //verification code container background image,
* Yverifycode blog: https://feifeiyum.github.io/2017/01/04/front-verify-code/
*/

//定义Yverifycode
var Yverifycode = (function() {
var NewVC = function(opt) {
//初始化值校验
if(opt.input === undefined) {
throw 'verification code input Dom target id can\'t be null'
}
if(opt.container === undefined) {
throw 'verification code image Dom container target id can\'t be null'
}
if(opt.reset !== undefined && typeof opt.reset !== 'string') {
throw 'type of verification code reset dom id is string '
}
if(opt.length !== undefined && typeof opt.length !== 'number') {
throw 'type of verification code length is number'
}
if(opt.width !== undefined && typeof opt.width !== 'number') {
throw 'type of verification code window width is number'
}
if(opt.bgColor !== undefined && !/^#([a-f0-9A-F]{3}|[a-f0-9A-F]{6})$/.test(opt.bgColor)) {
throw 'type of verification code background color is hex'
}
if(opt.bgImg !== undefined && typeof opt.bgImg !== 'string') {
throw 'type of verification code background image is url(string)'
}

this.input = document.getElementById(opt.input)
opt.reset && (this.reset = opt.reset)
this.container = opt.container
this.length = opt.length || 4
this.width = opt.width || 100
opt.bgColor && (this.bgColor = opt.bgColor)
opt.bgImg && (this.bgImg = opt.bgImg)
this.code = ''

//初始化
this.init()
}
//初始化函数
NewVC.prototype.init = function() {
var self = this
self.styleOption()

self.genDom()
self.drawCode()
self.drawLines()

if(self.reset) {
document.getElementById(self.reset).addEventListener('click', function() {
self.refresh.call(self)
}, false)
}
}
//随机数生成器
NewVC.prototype.randInt = function(start, end) {
!start && (start = 0)
!end && (end = 10)
var distance = end - start
var num = Math.random() * distance + start
return Math.floor(num)
}
//生成随机校验码
NewVC.prototype.genRandStr = function() {
var codeChars = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]

for(var i = 0; i < this.length; i++) {
this.code += (codeChars[this.randInt(0, codeChars.length)])
}
}
//生成校验码图片框
NewVC.prototype.genDom = function() {
this.codeWin = document.createElement('div')
this.codeWin.style.cssText = 'position:relative;width:100%;height:100%;overflow: hidden;'
if(this.bgImg) {
this.codeWin.style.cssText += 'background: url(' + this.bgImg + ') no-repeat;'
+ 'background-size: 100% 100%;'
} else if(this.bgColor) {
this.codeWin.style.cssText += 'background: ' + this.bgColor + ';'
}
document.getElementById(this.container).appendChild(this.codeWin)
}
//校验码样式表
NewVC.prototype.styleOption = function() {
this.codeStyle = {
fontSizeMin: 20,
fontSizeMax: 38,
colors: [
'#00FF00',
'#0000FF',
'#FF0000',
'#53da33',
'#AA0000',
'#FFBB00',
'#551A8B',
'#8B008B'
],
fonts: [
'Microsoft Yahei',
'tahoma',
'arial',
'Hiragino Sans GB',
'helvetica neue',
'helvetica',
'arial',
'Sans-serif',
'Hiragino Sans GB',
'Hiragino Sans GB W3',
'SimHei'
],
lineColors: [
'#888888',
'#FF7744',
'#888800',
'#008888'
],
lineStyles: [
'dashed',
'solid',
'dotted',
'double',
'ridge'
]
}
}
//绘制随机校验码
NewVC.prototype.drawCode = function() {
this.genRandStr()
var widthUnit = (this.codeWin.clientWidth || this.width) / this.code.length
console.log('widthUnit', widthUnit)
for(var i = 0; i < this.code.length; i++) {
var codeDom = document.createElement('span')
codeDom.style.cssText = 'position:absolute;'
+ 'top:' + this.randInt(0, 15) + '%;'
+ 'left:' + this.randInt(widthUnit * i, widthUnit * i + widthUnit - 20) + 'px;'
+ 'font-size:' + this.randInt(this.codeStyle.fontSizeMin, this.codeStyle.fontSizeMax) + 'px;'
+ 'color:' + this.codeStyle.colors[this.randInt(0, this.codeStyle.colors.length)] + ';'
+ 'font-family:' + this.codeStyle.fonts[this.randInt(0, this.codeStyle.fonts.length)] + ';'
+ 'font-weight:' + this.randInt(200, 900) + ';'
+ 'transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-ms-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-webkit-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-ms-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-moz-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-o-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
codeDom.innerHTML = this.code[i]
this.codeWin.appendChild(codeDom)
}
}
//绘制干扰线条
NewVC.prototype.drawLines = function() {
for(var i = 0; i < 8; i++) {
var lineDom = document.createElement('hr')
lineDom.style.cssText = 'position:absolute;'
+ 'top:' + this.randInt(0, 99) + '%;'
+ 'left:' + this.randInt(0, 80) + '%;'
+ 'border:0;'
+ 'border-top:' + this.randInt(1, 5) + 'px ' + this.codeStyle.lineStyles[this.randInt(0, this.codeStyle.lineStyles.length)] + ';'
+ 'border-color:' + this.codeStyle.lineColors[this.randInt(0, this.codeStyle.lineColors.length)] + ';'
+ 'width:' + this.randInt(10, this.codeWin.clientWidth) + 'px;'
+ 'opacity:' + this.randInt(3, 8) / 10 + ';'
+ 'transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-ms-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-webkit-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-ms-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-moz-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
+ '-o-transform:rotate(' + this.randInt(-35, 35) + 'deg);'
this.codeWin.appendChild(lineDom)
}
}
//清空校验码
NewVC.prototype.clean = function() {
this.input.value = ''
this.code = ''
this.codeWin.innerHTML = ''
}
//更新校验码
NewVC.prototype.refresh = function() {
this.clean()
this.drawCode()
this.drawLines()
}
//获取校验结果
NewVC.prototype.verify = function() {
var inputCode = this.input.value
inputCode = inputCode.trim().toLowerCase()
var code = this.code.toLowerCase()
if(inputCode === code) {
return true
} else {
return false
}
}

return NewVC
}())

//采用模块化引入时使用该句
//module.exports = Yverifycode

END