<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基于Python實現(xiàn)原生的登錄驗證碼

          共 5061字,需瀏覽 11分鐘

           ·

          2021-10-16 14:15

          目錄

          • 1、概述

          • 2、驗證碼實現(xiàn)的演進過程

            • 2.1 路由及頁面

            • 2.2 視圖函數(shù)中驗證碼的推導

            • 2.3 登錄驗證中使用驗證碼

            • 2.4 前端頁面點擊自動刷新

          • 3、效果展示

          • 4、小結(jié)


          1、概述

          在前面的文章中,我有分享到?vue+drf+第三方滑動驗證碼的接入實現(xiàn)?[1](文中也留了坑分享圖片驗證碼功能的實現(xiàn)),即本文將要分享的是基于python實現(xiàn)原生的登錄驗證碼

          通常的驗證碼,人眼看上去更像是一張小圖片

          html語法中,嵌入一張圖片一般用img標簽實現(xiàn),而img標簽對應的src一般有以下幾種寫法

          • 圖片的本地路徑
          • 圖片的 url
          • 圖片的二進制數(shù)據(jù)(base64 編碼)

          其中前兩種方法都需要外部具有實際存在的圖片,第三種方法則是將圖片進行編碼后填充到img標簽的src

          2、驗證碼實現(xiàn)的演進過程

          2.1 路由及頁面

          為了實現(xiàn)驗證碼的功能,需要開設一個url單獨處理驗證碼功能,修改全局路由

          urlpatterns?=?[
          ????......
          ????url(r'^login/',?views.login,?name='login'),
          ????#?圖片驗證碼
          ????url(r'^get_code/',?views.get_code,?name='gc'),
          ????...
          ]

          然后修改前端登錄頁面login.html的驗證碼部分

          ...
          <div?class="form-group">
          ????<label?for="">驗證碼label>
          ????<div?class="row">
          ????????<div?class="col-md-6">
          ????????????<input?type="text"?name="code"?id="id_code"?class="form-control">
          ????????div>
          ????????<div?class="col-md-6">
          ????????????<img?src="/get_code/"?alt=""?width="430"?height="35"?id="id_img">
          ????????div>
          ????div>

          div>
          <input?type="button"?class="btn?btn-success"?value="登陸"?id="id_commit">
          ...

          2.2 視圖函數(shù)中驗證碼的推導

          2.2.1 圖片發(fā)送到前端

          前端界面實現(xiàn)了一個簡單的包含驗證碼的登錄框,首先定義一個視圖函數(shù)將后端的測試圖片以二進制的形式發(fā)送到前端進行測試

          def?get_code(request):
          ????#?直接獲取后端現(xiàn)成的圖片二進制數(shù)據(jù)發(fā)送給前端
          ????with?open(r'static/img/test.jpg','rb')?as?f:
          ????????data?=?f.read()
          ????return?HttpResponse(data)

          2.2.2 引入動態(tài)圖片

          為了操作圖片,主要利用的是pillow模塊

          pip3?install?pillow

          主要用到了Image、ImageDrawImageFont

          • Image:生成圖片
          • ImageDraw:在圖片上定義內(nèi)容
          • ImageFont:控制字體樣式

          因此,利用pillow模塊動態(tài)產(chǎn)生圖片的方法為

          import?random
          from?PIL?import?Image,?ImageDraw,?ImageFont

          def?get_random():
          ????return?random.randint(0,?255),?random.randint(0,?255),?random.randint(0,?255)


          def?get_code(request):
          ????#?利用pillow模塊動態(tài)產(chǎn)生圖片
          ????#?img_obj?=?Image.new('RGB',(430,35),'green')??#?RGB組合、圖片尺寸、顏色
          ????img_obj?=?Image.new('RGB',(430,35),get_random())??#?通過色值指定顏色
          ????#?先將圖片對象保存起來
          ????with?open('xxx.png','wb')?as?f:
          ????????img_obj.save(f,'png')
          ????#?再將圖片對象讀取出來
          ????with?open('xxx.png','rb')?as?f:
          ????????data?=?f.read()
          ????return?HttpResponse(data)

          2.2.3 內(nèi)存管理模塊圖片

          上面將圖片對象保存在讀取有些麻煩,文件存儲繁瑣IO操作效率低 ,可以借助于內(nèi)存管理器模塊實現(xiàn)

          其中又分為BytesIOStringIO兩種

          • BytesIO:臨時存儲數(shù)據(jù),返回的時候數(shù)據(jù)是二進制
          • StringIO:臨時存儲數(shù)據(jù),返回的時候數(shù)據(jù)是字符串

          內(nèi)存管理對象就相當于上面的文件句柄

          import?random
          from?PIL?import?Image,?ImageDraw,?ImageFont

          def?get_random():
          ????return?random.randint(0,?255),?random.randint(0,?255),?random.randint(0,?255)


          def?get_code(request):
          ????img_obj?=?Image.new('RGB',?(430,?35),?get_random())
          ????io_obj?=?BytesIO()??#?生成一個內(nèi)存管理器對象??你可以看成是文件句柄
          ????img_obj.save(io_obj,'png')
          ????return?HttpResponse(io_obj.getvalue())??#?從內(nèi)存管理器中讀取二進制的圖片數(shù)據(jù)返回給前端

          這樣一來,圖片的生成以及返回就比較友好了

          2.2.4 完整圖片驗證碼

          上面解決了圖片如何傳遞到前端頁面的問題,剩下的就是如何生成對應的隨機驗證碼了

          例如隨機驗證碼為五位數(shù)的隨機驗證碼,包含數(shù)字、小寫字母、大寫字母

          import?random
          from?PIL?import?Image,?ImageDraw,?ImageFont

          def?get_random():
          ????return?random.randint(0,?255),?random.randint(0,?255),?random.randint(0,?255)


          def?get_code(request):
          ????#?寫圖片驗證碼
          ????img_obj?=?Image.new('RGB',?(430,?35),?get_random())
          ????img_draw?=?ImageDraw.Draw(img_obj)??#?產(chǎn)生一個畫筆對象
          ????#?引入本地的字體文件,指定字體樣式及字體大小
          ????img_font?=?ImageFont.truetype('static/font/222.ttf',?30)
          ????#?隨機驗證碼?五位數(shù)的隨機驗證碼??數(shù)字?小寫字母?大寫字母
          ????code?=?''
          ????for?i?in?range(5):
          ????????random_upper?=?chr(random.randint(65,?90))??#?隨機大寫字母
          ????????random_lower?=?chr(random.randint(97,?122))??#?隨機小寫字母
          ????????random_int?=?str(random.randint(0,?9))??#?隨機數(shù)字
          ????????#?每次從上面三個里面隨機選擇一個
          ????????tmp?=?random.choice([random_lower,?random_upper,?random_int])
          ????????#?將產(chǎn)生的隨機字符串寫入到圖片上,需要調(diào)整每個字體所在的坐標變換
          ????????img_draw.text((i?*?60?+?60,?-2),?tmp,?get_random(),?img_font)
          ????????#?拼接隨機字符串
          ????????code?+=?tmp
          ????print(code)
          ????#?隨機驗證碼在登陸的視圖函數(shù)里面需要要比對,所以要找地方存起來并且其他視圖函數(shù)也能拿到
          ????request.session['code']?=?code
          ????io_obj?=?BytesIO()
          ????img_obj.save(io_obj,?'png')
          ????return?HttpResponse(io_obj.getvalue())

          這里有一點,在寫入隨機文字的時候一個個寫而不是生成好了之后再寫,是因為一個個寫能夠控制每個字體的間隙。而生成好之后再寫的話,間隙就沒法控制了

          2.3 登錄驗證中使用驗證碼

          上面將每次生成的驗證碼存儲到了session中,這樣在前端傳過來的驗證碼,登錄校驗時就可以進行比對了

          ......
          def?login(request):
          ????if?request.method?==?'POST':
          ????????back_dic?=?{'code':?1000,?'msg':?''}
          ????????username?=?request.POST.get('username')
          ????????password?=?request.POST.get('password')
          ????????code?=?request.POST.get('code')
          ????????#?1?先校驗驗證碼是否正確??自己決定是否忽略大小寫?統(tǒng)一轉(zhuǎn)大寫或小寫再比較
          ????????if?request.session.get('code').upper()?==?code.upper():
          ????????????#?校驗用戶名和密碼是否正確
          ????????????user_obj?=?auth.authenticate(request,username=username,password=password)
          ????????????if?user_obj:
          ????????????????#?保存用戶狀態(tài)
          ????????????????auth.login(request,user_obj)
          ????????????????back_dic['url']?=?'/home/'
          ????????????else:
          ????????????????back_dic['code']?=?2000
          ????????????????back_dic['msg']?=?'用戶名或密碼錯誤'
          ????????else:
          ????????????back_dic['code']?=?3000
          ????????????back_dic['msg']?=?'驗證碼錯誤'
          ????????return?JsonResponse(back_dic)
          ????return?render(request,?'login.html')

          2.4 前端頁面點擊自動刷新

          最后,還留下一點小問題,前端在輸入驗證碼錯誤后不會自動刷新,如果點擊驗證碼也不會進行刷新,只能通過刷新登錄頁面才能刷新驗證碼,因此需要想辦法讓用戶在點擊驗證碼時自動刷新(單獨觸發(fā)驗證碼的視圖函數(shù))

          每次在點擊時,修改對應src的值即可,可以通過一小段js實現(xiàn)

          ...
          ???????<div?class="form-group">
          ????????????<label?for="">驗證碼label>

          ????????????<div?class="row">
          ????????????????<div?class="col-md-6">
          ????????????????????<input?type="text"?name="code"?id="id_code"?class="form-control">
          ????????????????div>
          ????????????????<div?class="col-md-6">
          ????????????????????<img?src="/get_code/"?alt=""?width="430"?height="35"?id="id_img">
          ????????????????div>
          ????????????div>

          ????????div>
          ????????<input?type="button"?class="btn?btn-success"?value="登陸"?id="id_commit">
          ...
          <script>
          ????$("#id_img").click(function?()?{
          ????????//?獲取標簽之前的src
          ????????let?oldVal?=?$(this).attr('src');
          ????????$(this).attr('src',oldVal?+=?'?')
          ????})
          script>

          3、效果展示

          最終前端的驗證碼效果如圖

          4、小結(jié)

          本文基于python以及相關(guān)的庫原生實現(xiàn)了登錄驗證碼邏輯~

          其實寫本文也是因為之前有過想法但是一段時間就忘了,最近通過某銀行手機銀行app重置登錄密碼的時候,發(fā)現(xiàn)其驗證碼顯示效果和本文效果竟然神似~,于是撿起來寫了此文

          其手機app驗證碼效果如下

          See you ~

          參考資料

          [1]

          https://www.ssgeek.com/post/vuedrfdi-san-fang-hua-dong-yan-zheng-ma-de-jie-ru-shi-xian/

          ? 歡迎進群一起進行技術(shù)交流

          ? 加群方式:公眾號消息私信“加群或加我好友再加群均可

          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色一级电影网站 | 香蕉国产成人毛片 | 天天综合~91入口 | 亚洲中文版字幕 | 操骚屄在线视频 |