Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
上回,上次和大家簡(jiǎn)單的介紹了下web驗(yàn)證碼實(shí)現(xiàn),也說(shuō)了異步刷新驗(yàn)證碼的實(shí)現(xiàn)邏輯,不過(guò)有些小伙伴還是建議我實(shí)現(xiàn)下,廢話少說(shuō),上代碼:此代碼是需要依賴:sanic==19.9.0Pillow==7.0.0
篇文章給大家整理的是關(guān)于python web框架Flask實(shí)現(xiàn)圖形驗(yàn)證碼的相關(guān)知識(shí)點(diǎn),有需要的朋友們參考下。下列代碼都是以自己的項(xiàng)目實(shí)例講述的,相關(guān)的文本內(nèi)容很少,主要說(shuō)明全在代碼注釋中:
自制圖形驗(yàn)證碼
這里所說(shuō)的圖形驗(yàn)證碼都是自制的圖形,通過(guò)畫布、畫筆、畫筆字體的顏色繪制而成的。將驗(yàn)證碼封裝成一個(gè)類比較好管理,代碼里有絕對(duì)詳細(xì)的注釋,當(dāng)然大家可以直接復(fù)制。
里面涉及的字體都是從系統(tǒng)電腦上自帶的,大家直接復(fù)制當(dāng)前目錄下就可以了。
主目錄/utils/captcha/__init__.py import random import string # Image:一個(gè)畫布 # ImageDraw:一個(gè)畫筆 # ImageFont:畫筆的字體 from PIL import Image, ImageDraw, ImageFont # Captcha驗(yàn)證碼 class Captcha(object): # 生成4位數(shù)的驗(yàn)證碼 numbers = 4 # 驗(yàn)證碼圖片的寬度和高度 size = (100, 30) # 驗(yàn)證碼字體大小 fontsize = 25 # 加入干擾線的條數(shù) line_number = 2 # 構(gòu)建一個(gè)驗(yàn)證碼源文本 SOURCE = list(string.ascii_letters) for index in range(0, 10): SOURCE.append(str(index)) # 用來(lái)繪制干擾線 @classmethod def __gene_line(cls, draw, width, height): begin = (random.randint(0, width), random.randint(0, height)) end = (random.randint(0, width), random.randint(0, height)) draw.line([begin, end], fill=cls.__gene_random_color(), width=2) # 用來(lái)繪制干擾點(diǎn) @classmethod def __gene_points(cls, draw, point_chance, width, height): # 大小限在【0, 100】中 chance = min(100, max(0, int(point_chance))) for w in range(width): for h in range(height): tmp = random.randint(0, 100) if tmp > 100 - chance: draw.point((w, h), fill=cls.__gene_random_color()) # 生成隨機(jī)顏色 @classmethod def __gene_random_color(cls, start=0, end=255): random.seed() return (random.randint(start, end), random.randint(start, end), random.randint(start, end)) # 隨機(jī)選擇一個(gè)字體 @classmethod def __gene_random_font(cls): fonts = [ "PAPYRUS.TTF", "CENTAUR.TTF", "Inkfree.ttf", "verdana.ttf", ] font = random.choice(fonts) return "utils/captcha/"+font # 用來(lái)隨機(jī)生成一個(gè)字符串(包括英文和數(shù)字) @classmethod def gene_text(cls, numbers): # numbers是生成驗(yàn)證碼的位數(shù) return " ".join(random.sample(cls.SOURCE, numbers)) # 生成驗(yàn)證碼 @classmethod def gene_graph_captcha(cls): # 驗(yàn)證碼圖片的寬高 width, height = cls.size # 創(chuàng)建圖片 image = Image.new("RGBA", (width, height), cls.__gene_random_color(0, 100)) # 驗(yàn)證碼的字體 font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize) # 創(chuàng)建畫筆 draw = ImageDraw.Draw(image) # 生成字符串 text = cls.gene_text(cls.numbers) # 獲取字體的尺寸 font_width, font_height = font.getsize(text) # 填充字符串 draw.text(((width-font_width)/2, (height-font_height)/2), text, font=font, fill=cls.__gene_random_color(150, 255)) # 繪制干擾線 for x in range(0, cls.line_number): cls.__gene_line(draw, width, height) # 繪制干擾點(diǎn) cls.__gene_points(draw, 10, width, height) with open("captcha.png", "wb") as fp: image.save(fp) return text, image
一般圖形驗(yàn)證碼都是在表單中,這樣短時(shí)間內(nèi)的數(shù)據(jù)及建議保存在redis緩存中(用戶點(diǎn)擊動(dòng)態(tài)刷新圖形驗(yàn)證碼)。首先我們繪制圖形驗(yàn)證碼保存到項(xiàng)目的目錄下(入口文件是主目錄(項(xiàng)目目錄)app.py文件,圖片也保存到主目錄下),然后通過(guò)url地址訪問(wèn)自制的圖形驗(yàn)證碼(這里我只添加主要的代碼)顯示圖形驗(yàn)證碼
主目錄/common/views.py @bp.route("/captcha") def graph_captcha(): """ 使用定義好的圖形驗(yàn)證碼類,來(lái)制作驗(yàn)證碼 以驗(yàn)證碼為鍵、驗(yàn)證碼為值(為了用戶的體驗(yàn),讓其忽略大小寫)存儲(chǔ)在redis緩存中 通過(guò)BytesIO字節(jié)流的方式保存和訪問(wèn)圖片 :return: 圖片響應(yīng) """ # 獲取驗(yàn)證碼 text, image = Captcha.gene_graph_captcha() cpcache.set(text.lower(), text.lower()) # BytesIO:字節(jié)流 out = BytesIO() # 保存圖片 image.save(out, "png") # 存儲(chǔ)完圖片,將文件的指針指向文件頭,使下次保存圖片能覆蓋前面保存的圖片,節(jié)省空間 out.seek(0) # 訪問(wèn)圖片,并將其作為一個(gè)響應(yīng)返回給前臺(tái) resp = make_response(out.read()) resp.content_type = "image/png" return resp
前端頁(yè)面的代碼如下:
<div class="form-group"> <div class="input-group"> <input type="text" class="form-control" name="graph_captcha" placeholder="圖形驗(yàn)證碼"> <span class="input-group-addon captcha-addon"> <img id="captcha-img" class="captcha-img" src="{{ url_for("common.graph_captcha") }}" alt=""> </span> </div> </div>
無(wú)非就是再生成一張圖形驗(yàn)證碼,通過(guò)url再次訪問(wèn)就可以,但是這樣做是非常麻煩的,這里我很難解釋(很難!!!),大家就直接復(fù)制代碼吧,這個(gè)代碼就是點(diǎn)擊圖片生成一個(gè)新的url訪問(wèn)圖片動(dòng)態(tài)刷新驗(yàn)證碼
這個(gè)文件放在公共的目錄下就可以了 var cpparam = { setParam: function(href, key, value){ //重新加載整個(gè)頁(yè)面 var isReplaced = false; var urlArray = href.split("?"); if(urlArray.length > 1){ var queryArray = urlArray[1].split("&"); for(var i=0; i < queryArray.length; i++){ var paramArray = queryArray[i].split("="); if(paramArray[0] == key){ paramArray[1] = value; queryArray[i] = paramArray.join("="); isReplaced = true; break; } } if(!isReplaced){ var params = {}; params[key] = value; if(urlArray.length > 1){ href = href + "$" + $.param(params); }else{ href = href + "?" + $.param(params); } }else{ var params = queryArray.join("&"); urlArray[1] = params; href = urlArray.join("?"); } }else{ var param = {}; param[key] = value; if(urlArray.length > 1){ href = href + "$" + $.param(param); }else{ href = href + "?" + $.param(param); } } return href; } };
對(duì)應(yīng)html的js文件就需要實(shí)現(xiàn)元素(圖片)點(diǎn)擊刷新圖片,調(diào)用上面的變量cpparam生成一章圖片并訪問(wèn)。
$(function(){ $("#captcha-img").on("click", function(){ var self = $(this); var src = self.attr("src"); var newsrc = cpparam.setParam(src, "xx", Math.random()); self.attr("src", newsrc); }); });
以上就是本次介紹的關(guān)于python web框架Flask實(shí)現(xiàn)圖形驗(yàn)證碼全部知識(shí)點(diǎn)內(nèi)容,覺(jué)得文章還不錯(cuò)的話不妨點(diǎn)個(gè)贊,有任何建議或看法歡迎大家在評(píng)論區(qū)分享討論!
我是一名python開發(fā)工程師,整理了一套python的學(xué)習(xí)資料,如果你想提升自己,對(duì)編程感興趣,關(guān)注我并在后臺(tái)私信小編:“08”即可免費(fèi)領(lǐng)取資料!希望對(duì)你能有所幫助!
是個(gè)發(fā)送驗(yàn)證碼時(shí)常用的功能,當(dāng)用戶點(diǎn)擊【發(fā)送驗(yàn)證碼】之后出現(xiàn)【重新獲取60s后】。在倒計(jì)時(shí)期間禁止用戶繼續(xù)發(fā)送驗(yàn)證碼,待倒計(jì)時(shí)結(jié)束之后才可以再次發(fā)送驗(yàn)證碼。這個(gè)可以避免重復(fù)發(fā)送請(qǐng)求獲取多個(gè)驗(yàn)證碼信息(但是只有最后一次才是有效的),你也不知道自己發(fā)送了幾次請(qǐng)求,當(dāng)手機(jī)接收到驗(yàn)證碼之后容易誤以為是正確的驗(yàn)證碼。所以做適當(dāng)?shù)目刂剖欠浅S斜匾模瑫r(shí)也可以防止惡意發(fā)送請(qǐng)求消耗服務(wù)器資源。
為了方便這里我們用ElementUI來(lái)實(shí)現(xiàn),在el-form-item中利用el-button按鈕來(lái)實(shí)現(xiàn)驗(yàn)證碼發(fā)送。發(fā)送驗(yàn)證碼之后直接在el-button上修改現(xiàn)實(shí)中在HTML中的【發(fā)送驗(yàn)證碼】?jī)?nèi)容,利用disabled屬性來(lái)控制el-button的是否可以點(diǎn)擊。
定義一個(gè)retrieve()方法開啟倒計(jì)時(shí)功能,利用setInterval計(jì)時(shí)器每隔一秒鐘調(diào)用一次函數(shù),當(dāng)?shù)褂?jì)時(shí)結(jié)束時(shí)通過(guò)clearInterval()來(lái)關(guān)閉計(jì)時(shí)器。這里我們需要做的是刷新時(shí)間和重定義el-button中的HTML內(nèi)容,disable是用來(lái)控制el-button按鈕是否可點(diǎn)擊的屬性。注意:disabled屬性別用this.$refs.onConfirm.disbaled=true來(lái)定義,會(huì)報(bào)警告的:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "disabled"。
在發(fā)送之前我們需要對(duì)表單中的數(shù)據(jù)進(jìn)行校驗(yàn),這里為什么要嵌套兩個(gè)validateField呢(validateField支持校驗(yàn)組數(shù))?。因?yàn)関alidateField校驗(yàn)子表單數(shù)據(jù)時(shí)每校驗(yàn)一個(gè)值都會(huì)返回校驗(yàn)結(jié)果,當(dāng)校驗(yàn)不通過(guò)時(shí)Error返回值為校驗(yàn)的提示信息,當(dāng)通過(guò)時(shí)Error的值為空,所以我們?cè)趇f語(yǔ)句中用(!Error)表示校驗(yàn)通過(guò)。那么這就存在一個(gè)問(wèn)題如果校驗(yàn)數(shù)組的話就會(huì)進(jìn)行多次校驗(yàn),也就會(huì)發(fā)送多次驗(yàn)證請(qǐng)求。(點(diǎn)一次請(qǐng)求卻收到多條驗(yàn)證碼這顯然是不合理的!)
這里主要的就是retrieve()方法的定義和動(dòng)態(tài)改變HTML內(nèi)容,可以利用Vue提供的$ref來(lái)快速的定位DOM元素實(shí)現(xiàn)屬性的修改。以上內(nèi)容是小編給大家分享的【Vue實(shí)戰(zhàn)088:簡(jiǎn)單的驗(yàn)證碼倒計(jì)時(shí)功能實(shí)現(xiàn)】,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。更多Vue實(shí)戰(zhàn)技巧可以參考以下專欄:
為了方便學(xué)習(xí),下面附上本文用到的源碼:
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。