前言 最近在开发行为验证码,经常触及到关于验证类型的相关内容。但使用起来不太熟练,闲暇之余,总结一下我对行为验证码验证类型的理解。 验证类型概述 滑动拼图 创新行为式验证,轻松一滑完成拼图,体验极佳,秒速通过验证。简洁高效,在保障用户极致体验的同时,抵御机器风险。适用于追求用户体验的场景。生成背景图basemap1Image。open(bg)。convert(RGBA)背景图ifbasemap1。size!size:需要裁切或拉伸basemap1Graphics。crop(basemap1,size〔0〕,size〔1〕)puzzle1Image。open(urlabsolute(img))。convert(RGBA)方块图,蒙板旋转角度ifrotate2:anglerandint(0,360)elifrotate1:anglechoice(〔0,90,180,270〕)else:angle0angle45ifangle:puzzle1puzzle1。rotate(angle,resampleImage。Resampling。BILINEAR)puzzle1。putalpha(ImageEnhance。Brightness(puzzle1。split()〔3〕)。enhance(alpha))设置透明度,01之间产生随机位置imgsizepuzzle1。size滑动图片尺寸spacing0滑动图片在底图位置四周间距,暂时使用0,小图片中的图案本身有20px边距随机位置xrandint(imgsize〔0〕spacing,size〔0〕imgsize〔0〕spacing)yrandint(spacing,size〔1〕imgsize〔1〕spacing)basemap1。paste(puzzle1,(x,y),puzzle1)拷贝方块滑动图basemap2Image。open(urlabsolute(bg))。convert(RGBA)basemap2Image。open(bg)。convert(RGBA)ifbasemap2。size!size:需要裁切或拉伸basemap2Graphics。crop(basemap2,size〔0〕,size〔1〕)puzzle2Image。open(urlabsolute(img))。convert(RGBA)ifangle:puzzle2puzzle2。rotate(angle,resampleImage。Resampling。BILINEAR)旋转basemap2basemap2。crop((x,y,ximgsize〔0〕,yimgsize〔1〕))裁切puzzle2。paste(basemap2,(0,0),puzzle2)替换成长条形滑动块stripImage。new(RGBA,(imgsize〔0〕,size〔1〕),(255,255,255,0))strip。paste(puzzle2,(0,y),puzzle2)拷贝 文字点选 顺序点击图中文字,全新行为验证,安全性极高,保障验证安全。提高机器识别难度的同时,保证真实用户可读。适用于安全要求较高的业务场景。defrandomcharacter(self,lengthNone,type〔0,1,2,3〕,repeatFalse):生成随机字符:paramlength:生成的字符长度,几个字符:paramtype:〔0〕数字,〔1〕大写字母,〔2〕小写字母,〔3〕特殊字符:paramrepeat:是否允许重复字符:return〔(A,1,大写字母),(8,0,数字),(a,2,小写字母),(,3,高跟鞋)。。。〕iflengthisNone:lengthself。strcountlength10type〔0〕string。join(dict(〔(key,{0:2345678923456789,1:ABCDEFGHJKLMNQRTY,2:abcdefghijkmnqrty,3:,}〔key〕)forkeyintype〕)。values())r〔〕foriinrange(length):ifrepeat:允许重复schoice(string)tInference。chartype(s)r。append((s,t〔0〕,t〔1〕))else:anti0防止死循环,尝试一定次数后允许字符重复whileTrue:anti1schoice(string)tInference。chartype(s)st。join(〔it〔0〕foritinr〕)ifsnotinstoranti30:r。append((s,t〔0〕,t〔1〕))break替换n个字母为图形字符if3intype:indexsample(〔iforiinrange(length)〕,randint(0,length))随机一组索引值:〔0,3,1〕iconcharsample(self。iconstr,len(index))随机取出n组特殊字符x0foriinindex:rInference。charreplace(r,i,iconchar〔x〕〔1〕)r〔i〕(iconchar〔x〕〔1〕,3,iconchar〔x〕〔2〕)x1returnr 语序点选 根据中文语义,按顺序依次点击图中文字,语义理解能力结合行为轨迹。适用于安全要求较高的业务场景。 下面举例说说的干扰点与干扰线的制作:噪线foriinrange(linecount):x1randint(0,size〔0〕)x2randint(0,size〔0〕)y1randint(0,size〔1〕)y2randint(0,size〔1〕)draw。line((x1,y1,x2,y2),fillWord。getrandomcolor())噪点foriinrange(pointcount):draw。point(〔randint(0,size〔0〕),randint(0,size〔1〕)〕,fillWord。getrandomcolor())xrandint(0,size〔0〕)yrandint(0,size〔1〕)draw。arc((x,y,x4,y4),0,90,fillWord。getrandomcolor()) 字体识别 点击与其它字符不同字体的文字,用户仅需一次点击,即可进行安全验证。适用于安全要求超高的业务场景。字体识别iftypein(10,11,12):789生成成语固定字符strcount1strinternumeric(strinter,2,20)干扰字符不能少于2vfontsample(ttf,2)随机选出两种字体string〔〕foriinrange(strcountstrinter):iftypein(10,11,12):字体识别,只使用两种字体fontfilevfont〔0〕ifi0elsevfont〔1〕else:随机字体fontfilechoice(ttf)fontImageFont。truetype(urlabsolute(fontfile),sizefontsize)成语使用固定字符,前n个字符使用成语字符randomcharidiom〔i:i1〕ifidiomelse随机字符串及补充固定字符时追加干扰字符ifrandomchar:headrandint(0xb0,0xf7)bodyrandint(0xa1,0xfe)randomcharbytes。fromhex(f{head:x}{body:x})。decode(gb18030)print(randomchar,fontfile)随机位置anti0防止字体设置过大或者图片设置过小,导致死循环,尝试一定次数后允许字符重叠whileTrue:防止文字重叠anti1xrandint(0,size〔0〕fontsize)yrandint(0,size〔1〕fontsize)findTrueforsinstring:ifabs(xs〔1〕)fontsizeandabs(ys〔2〕)fontsize:findFalsebreakiffindornotstringoranti20:break创建文字图片,可旋转strbgImage。new(RGBA,(fontsize,fontsize),(255,255,255,0))文字用空白图层strdrawImageDraw。Draw(strbg)strdraw。text((0,0),randomchar,Word。getrandomcolor(),fontfont)添加文字anglerandint(75,75)ifrotateelse0是否随机角度strbgstrbg。rotate(angle,resampleImage。Resampling。BILINEAR,expand0)随机旋转basemap。paste(strbg,(x,y),strbg)图片与文字合并保存随机字符及位置string。append(〔randomchar,x,y,angle〕)字符、x、y、角度(正负转换,转用CSS顺时针旋转形式) 空间推理 根据提示,点击对应的元素。逻辑解题能力结合图形符号等元素识别能力。适用于安全要求超高的业务场景。 下面举例几种验证方式:defsendcolor2differ(self):请点击一个颜色不一样的字符colorself。colorname(2)获取2组带中文名称的颜色〔(蓝色,0000FF),〕data〔〕foriinrange(self。strcount):data在图片上生成的数据data。append({str:self。string〔i〕〔0〕,字符内容X:self。coord〔i〕〔0〕,x位置Y:self。coord〔i〕〔1〕,y位置color:color〔0〕〔1〕ifi0elsecolor〔1〕〔1〕,angle:self。angle〔i〕,icon:Trueifself。string〔i〕〔1〕3elseFalse,是否为图形字符})hint操作说明文字hintf请点击一个i颜色不一样i的i{self。string〔0〕〔2〕}istr〔(data〔0〕〔str〕,data〔0〕〔X〕,data〔0〕〔Y〕,data〔0〕〔angle〕),〕return{data:data,str:str,hint:hint}defsendcolor2capital(self):请点击蓝色字母对应的大写direcchoice(〔1,2〕)随机一种方式,大写to小写小写to大写colorself。colorname()获取n组带中文名称的颜色〔(蓝色,0000FF),〕self。stringself。randomcharacter(type〔direc〕)data〔〕foriinrange(self。strcount):data在图片上生成的数据data。append({str:self。string〔i〕〔0〕,字符内容X:self。coord〔i〕〔0〕,x位置Y:self。coord〔i〕〔1〕,y位置color:color〔i〕〔1〕,angle:self。angle〔i〕,icon:Trueifself。string〔i〕〔1〕3elseFalse,是否为图形字符})data〔0〕〔str〕data〔1〕〔str〕。swapcase()hint操作说明文字hintf请点击i{color〔0〕〔0〕}字母i对应的i{大写ifdirec1else小写}istr〔(data〔1〕〔str〕,data〔1〕〔X〕,data〔1〕〔Y〕,data〔1〕〔angle〕),〕return{data:data,str:str,hint:hint}总结 以上便是本文的全部内容,相关代码我已经放上Github了,https:github。comKgCaptcha,这里我做了一个示例:https:www。kgcaptcha。comdemo。