1.基於Python實現,用到了django后台處理,刷新驗證碼功能,其他語言大同小異
2.登錄界面
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>DevOPS v1.0</title> <!-- Bootstrap Core CSS --> <link href="/static/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <!-- MetisMenu CSS --> <link href="/static/vendor/metisMenu/metisMenu.min.css" rel="stylesheet"> <!-- Custom CSS --> <link href="/static/dist/css/sb-admin-2.css" rel="stylesheet"> <!-- Custom Fonts --> <link href="/static/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css"> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div class="container"> <div class="row"> <div class="col-md-4 col-md-offset-4"> <div class="login-panel panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Please Sign In</h3> </div> <div class="panel-body"> <form role="form" action="/index/login/" method="post"> <fieldset> <div class="form-group"> <input class="form-control" placeholder="Username" name="username" type="text" autofocus> </div> <div class="form-group"> <input class="form-control" placeholder="Password" name="password" type="password" value=""> </div> <div class="form-group"> <input class="form-control" placeholder="驗證碼" name="yanzhengma" type="text" value=""> {# <span><img src={{ data }}></span>#} {# <span>{{ data }}</span>#} <img src="/index/yanzhengma/" onclick="ChangeCode(this);"/> <div style="color: red;">{{ msg }}</div> </div> <div class="checkbox"> <label> <input name="remember" type="checkbox" value="Remember Me">Remember Me </label> </div> <!-- Change this to a button or input when using this as a form --> {# <a href="/login/" class="btn btn-lg btn-success btn-block">Login</a>#} <input type="submit" class="btn btn-lg btn-success btn-block" name="Login"/> </fieldset> </form> </div> </div> </div> </div> </div> <!-- jQuery --> <script src="/static/vendor/jquery/jquery.min.js"></script> <!-- Bootstrap Core JavaScript --> <script src="/static/vendor/bootstrap/js/bootstrap.min.js"></script> <!-- Metis Menu Plugin JavaScript --> <script src="/static/vendor/metisMenu/metisMenu.min.js"></script> <!-- Custom Theme JavaScript --> <script src="/static/dist/js/sb-admin-2.js"></script> <script type="text/javascript"> function ChangeCode(ths) { var src_re = $(ths).attr('src'); $(ths).attr('src', src_re + '?'); } </script> </body> </html>
里面涉及到2個后端視圖函數login和get_yanzhengma
3.后端視圖函數
helper.py
# -*- coding=utf-8 -*- import random # 隨機字母: def rndChar(): return chr(random.randint(65, 90)) + chr(random.randint(65, 90)) + chr(random.randint(65, 90)) + chr(random.randint(65, 90))
Django的views.py
# -*- coding=utf-8 -*- ############################## from django.shortcuts import render, HttpResponse, render_to_response,redirect from app import models from helper import rndChar from PIL import Image, ImageFont, ImageDraw import io # Create your views here. def index(request): # return HttpResponse('123456') return render_to_response('app/pages/index.html') def login(request): if request.method == 'POST': print request.POST username = request.POST.get('username',None) password = request.POST.get('password',None) yanzhengma = request.POST.get('yanzhengma',None) # print yanzhengma,request.session['yanzhengma'] if yanzhengma.upper() != request.session['yanzhengma'].upper(): return render_to_response('app/pages/login.html',{'msg':'驗證碼錯誤'}) count = models.AdminInfo.objects.filter(username=username,password=password).count() if count > 0: request.session['is_login'] = {'user':username} return redirect('/index/') # return render_to_response('app/pages/index.html') else: return render_to_response('app/pages/login.html',{'msg':'賬戶密碼錯誤'}) else: # print stream.getvalue() # im.save("static/image/t.png") # request.session['yanzhengma'] = text return render_to_response('app/pages/login.html',{'msg':''}) def yanzhengma(request): #text為產生的4位隨機字符串 text = rndChar() # print text request.session['yanzhengma'] = text #圖片處理程序,將文本做成圖片 im = Image.new("RGB", (130, 35), (255, 255, 255)) dr = ImageDraw.Draw(im) font = ImageFont.truetype("arial", 24) # simsunb.ttf 這個從windows fonts copy一個過來 dr.text((10, 5), text, font=font, fill="#000000") # im.show() #創建一個io對象 stream = io.BytesIO() #將圖片對象im保存到stream對象里 im.save(stream, "png") #stream.getvalue()圖片二級制內容,再通過HttpResponse封裝,返回給前端頁面 return HttpResponse(stream.getvalue())
4.效果圖展示
5.備注:
(1)img標簽的src屬性,去這個/get_yanzhengma/去取圖片
(2)get_yanzhengma函數執行
(3)通過random模塊生成隨機碼,4個字母
(4)通過PIL模塊將隨機數字轉換為圖片對象im
(5)創建一個BytesIO對象,內存對象,可以存儲二進制的東西
(6)將圖片對象保存到BytesIO對象中,此處在內存里
#話說為什么要將圖片對象保存到BytesIO對象中而不是直接寫到硬盤里存為圖片文件呢?因為這樣就保證了在同一個時刻,不同用戶訪問到的驗證碼是不一樣的,而且都是存儲在內存中的。
#如果寫成驗證碼圖片文件到硬盤里,有可能B頁面顯示的驗證碼是ABCD,但是B用戶還沒提交,A用戶這會訪問,刷新了驗證碼,把驗證碼變更為DCBA了,B頁面里看到的還是ABCD,導致一直輸不對驗證碼;無法保證2個用戶的驗證碼圖片沖突問題
#后端驗證碼的隨機值是存儲在session中的,每次用戶GET請求,服務器上生成隨機驗證碼存儲在session中,並給頁面返回,如果用戶提交的驗證碼和后端session中記錄的一致通過,如果不一致,重新刷新驗證碼,用戶重新進行提交
(7)BytesIO對象的getvalue()方法返回二進制內容
(8)django提供的HttpResponse封裝二進制內容為識別的東西傳遞給前端
(7)前端img標簽正常顯示圖片
(9)用戶點擊圖片,js先獲取到這個圖片標簽,取到當前的src屬性值存為變量src_re,然后更改src的屬性值為src_re + ?
#為什么要加?呢是因為GET請求,每最后加一個?代表一個新的url,但是效果呢是和/index/yanzhengma/是一致的,每點一次,后面加一個?。/index/yanzhengma/? /index/yanzhengma/??這個意思
#如果每次只更改src的屬性值為/index/yanzhengma/的話,不會進行request請求,會直接瀏覽器緩存讀取。達不到刷新驗證碼的目的