web驗(yàn)證碼的簡(jiǎn)單實(shí)現(xiàn)

最近有小伙伴提問:能否說下web驗(yàn)證的原理,感覺文字描述不清楚,于是就用代碼簡(jiǎn)單的演示下:
此代碼是需要依賴:
sanic==19.9.0
Pillow==7.0.0

import random
import string
import uuid
import base64
import platform
from PIL import Image, ImageDraw,ImageFont
from io import BytesIO
from sanic import Sanic
from sanic.response import HTTPResponse,text
from sanic.views import HTTPMethodView


app = Sanic()

session = {}


class VerifyCode:
    def __init__(self, numbers:int):
        """
        指定:生成的數(shù)量
        """
        self.number = numbers

    def draw_lines(self, draw, num, width, height):
        """劃線"""

        x1 = random.randint(0, width / 2)
        y1 = random.randint(0, height / 2)
        x2 = random.randint(0, width)
        y2 = random.randint(height / 2, height)
        draw.line(((x1, y1), (x2, y2)), fill='black', width=1)

    def random_color(self):
        """隨機(jī)顏色"""
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

    def gene_text(self):
        """生成驗(yàn)證碼"""
        return "".join(random.sample(string.ascii_letters+string.digits, self.number))

    def get_verify_code(self):
        """
        draw.text():
            文字的繪制,第一個(gè)參數(shù)指定繪制的起始點(diǎn)(文本的左上角所在位置),第二個(gè)參數(shù)指定文本內(nèi)容,第三個(gè)參數(shù)指定文本的顏色,第四個(gè)參數(shù)指定字體(通過ImageFont類來定義)
        """
        code = self.gene_text()
        width, height = 130, 30
        im = Image.new("RGB", (width, height), "white")
        # 這里指定字體的路徑
        sysstr = platform.system()
        font = None
        if sysstr == "Windows":
            font = ImageFont.truetype("C:\WINDOWS\Fonts\STXINGKA.TTF", 25)
        elif sysstr == "Darwin":
            font = ImageFont.truetype('/Library/Fonts/AppleMyungjo.ttf', 25)
        draw = ImageDraw.Draw(im)
        for item in range(self.number):
            draw.text((5+random.randint(-5,5)+23*item, 5+random.randint(-5, 5)), text=code[item],
                      fill=self.random_color(), font=font)
            self.draw_lines(draw, self.number, width, height)
        return im, code


class SimpleView(HTTPMethodView):
    body = """
        <html>
            <head>
                <meta charset="UTF-8">
                    <title>登錄</title>
                    <link rel="stylesheet"  integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
                    <!-- 可選的 Bootstrap 主題文件(一般不用引入) -->
                    <link rel="stylesheet"  integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
                    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
                    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
            </head>
            <body>
                <form class="form-inline" method="post" action="/code">
                    <div>
                        <div class="form-group">
                            {error}                               
                          </div>
                        <div class="form-group">
                                <label for="exampleInputName2">驗(yàn)證碼</label>
                                <input type="text" class="form-control" id="captcha" name="code">
                        </div>
                        
                        <div class="form-group">
                            <img src="data:image/jpeg;base64,{base64_data}" class="img-img-rounded">
                        </div>
                        <div>
                            <button type="submit">驗(yàn)證</button>
                        </div>
                    </div>
                </form>
            </body>
        </html>
        """

    async def get(self, request):
        return self.response(error="")

    async def post(self, request):
        uuid = request.cookies.get("uuid", "1")
        verfy_code = request.form.get("code", "2").lower()
        code = session.get(uuid, "").lower()
        if code == verfy_code:
            return text('驗(yàn)證碼正確')
        return self.response(error='<input class="form-control" id="disabledInput" type="text" placeholder="驗(yàn)證碼錯(cuò)誤" disabled>')

    def response(self, error):
        im, code = VerifyCode(5).get_verify_code()
        buf = BytesIO()
        im.save(buf, "jpeg")
        buf_str = buf.getvalue()
        base64_data = base64.b64encode(buf_str).decode()
        id = uuid.uuid1().__str__()
        session[id] = code
        body = self.body.format(base64_data=base64_data, error=error)
        response = HTTPResponse(body, content_type="text/html; charset=utf-8")
        response.cookies["uuid"] = id
        return response


app.add_route(SimpleView.as_view(), '/code')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

只是簡(jiǎn)單的實(shí)現(xiàn)了驗(yàn)證碼,沒有實(shí)現(xiàn)點(diǎn)擊刷新,點(diǎn)擊刷新的原理不難:異步請(qǐng)求+刷新接口就好了,記得更新對(duì)應(yīng)的session的key里面的value

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 快速開始 在安裝Sanic之前,讓我們一起來看看Python在支持異步的過程中,都經(jīng)歷了哪些比較重大的更新。 首先...
    hugoren閱讀 19,984評(píng)論 0 23
  • 作者村上去了波士頓,冰島,俄勒岡州波特蘭,緬因州波特蘭,紐約,米克諾斯島,斯佩察島,芬蘭,老撾,意大利,夏目簌石故...
    飛舞的微辰閱讀 260評(píng)論 0 1
  • 一架飛機(jī),在天上飛呀飛。它遇到了小鳥,遇到了云彩,最后飛得比云彩還要高了。它飛呀飛呀,一直飛到機(jī)場(chǎng)里去。 一只小鳥...
    同言同語閱讀 211評(píng)論 0 2
  • 鄔澤祎,做什么事情都非常的認(rèn)真,聽故事,畫畫,剪紙,總是能認(rèn)真思考表達(dá)自己獨(dú)特的思維,我們?cè)O(shè)計(jì)重陽節(jié)的禮物,鄔澤祎...
    幼教一線人閱讀 375評(píng)論 0 1
  • 晚上睡覺的時(shí)候,媽媽的手機(jī)響了,爸爸為了不打擾到媽媽睡覺,接了電話,打算給對(duì)方說媽媽已經(jīng)睡下,有事情第二天再說。誰...
    家家有999本難念的經(jīng)閱讀 1,114評(píng)論 0 1

友情鏈接更多精彩內(nèi)容