自定義使用者和認證 中介軟體 檔案上傳/oss 圖片驗證碼
阿新 • • 發佈:2018-11-23
自定義使用者
寫一個繼承自AbstractUser的類,然後追加自己需要的欄位
在settings.py加入AUTH_USER_MODEL = 'app的名字.使用者類'
自定義使用者認證
步驟
在app的目錄下新鍵一個檔案 auth.py
寫一個繼承自ModeBackend
複寫authenticate函式(一個是找人,一個是校驗密碼)
在settings.py裡設定:AUTHENTICATION_BACKENDS="app的名字.檔名字.類"
使用和原生認證是一樣的
例子:
使用者的登入,註冊不做了,使用Django shell建立一個使用者 登入:使用者名稱 手機號 寫一個測試使用者是否登入的API
自定義認證類的具體實現
1 找人 1.1 使用使用者名稱搜尋 1.2 再按照電話號搜尋 2 校驗密碼 如果通過,返回user物件 否則返回None from django.contrib.auth.backends import ModelBackend from .models import MyUser class MyBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): # 找人 print("進入函式") try: user = MyUser.objects.get(username=username) print("沒找到") except Exception: try: user = MyUser.objects.get(phone=username) print(user.username, "找到了") except Exception as e: print(username, e) return None print("拿到使用者",user.username) # 密碼校驗 if user.check_password(password): return user else: return None
自定義中介軟體
在中介軟體進行使用者名稱的判斷 滿足條件直接返回
中介軟體應用: 我們可以做反爬蟲,可以做日誌統計,做錯誤統計,做快取
實現:
from django.http import HttpResponse, HttpResponseForbidden from django.utils.deprecation import MiddlewareMixin class YJMiddleWare(MiddlewareMixin): def process_request(self, request): # name = request.GET.get("name") # if name == "tom": # return HttpResponse("恭喜獲得特斯拉一輛") # elif name == "ada": # return HttpResponse("特斯拉模型一輛") # elif name == "班長": # return HttpResponse("咖妃") black_ips = [ "124.160.17.98", "101.68.87.26" ] # 獲取IP ip = request.META.get("REMOTE_ADDR") print(ip) if ip in black_ips: return HttpResponseForbidden("黑名單成員 無法訪問") else: return HttpResponse("歡迎進入真人賭場,體驗美女荷官")
在settings.py里加入
MIDDLEWARE = [
。。。。
'MiddleWares.MyAOP.YJMiddleWare' # 目錄名.檔名.類名
]
上傳檔案
class Book(models.Model):
name = models.CharField(
max_length=40
)
icon = models.ImageField(
upload_to="icons" # 指定檔案儲存的路徑名 系統自動建立
)
在settings.py 加入
配置上傳檔案目錄
MEDIA_ROOT = os.path.join(BASE_DIR, "static/uploads")
def create_book_v1(req):
# 解析引數
name = req.POST.get("name")
myfile = req.FILES.get("icon")
# 例項化一個數據
book = Book.objects.create(
name=name,
icon=myfile
)
return HttpResponse("ok")
如果想訪問圖片 需要自己拼接url
book = Book.objects.all().first()
# 拼接圖片的網路路徑
icon_url = "http://{}/static/uploads/{}".format(
req.get_host(), #獲取訪問的域名加埠
book.icon.url #圖片的路徑字串
)
生成隨機檔名
得到uuid字串
例項化md5
md5進行加密
得到32位16進位制的字串
import uuid
import hashlib
import random
def get_unique_str():
# 得到一個uuid的字串
uuid_str = str(uuid.uuid4()).encode("utf-8")
# 例項化md5
md5 = hashlib.md5()
# 進行加密
md5.update(uuid_str)
# 返回32位的十六進位制資料
return md5.hexdigest()
上傳檔案實現2
def create_book_v2(req):
if req.method == "GET":
return render(req, "mybook.html")
else:
# 拿到引數
name = req.POST.get("name")
myfile = req.FILES.get("icon")
# 檔案路徑
filename = get_unique_str() + "." + myfile.name.split(".")[-1]
filepath = os.path.join(settings.MEDIA_ROOT, filename)
f = open(filepath, "wb")
print(filename)
for i in myfile.chunks():
f.write(i)
f.close()
return HttpResponse("ok")
檔案上傳到oss
用的阿里雲
def upload_to_oss(req):
import oss2
endpoint = 'http://oss-cn-shanghai.aliyuncs.com'
access_key_id = 'LTA#########V9jSq'
access_key_secret = '7uXYe##############AWFkxIw'
bucket_name = 'share-msg'
bucket_name_host = "share-##Bucket 域名##ncs.com"
# 生成一個認證物件
auth = oss2.Auth(access_key_id, access_key_secret)
bucket = oss2.Bucket(auth, endpoint, bucket_name)
#獲取檔案
f = req.FILES.get("icon")
# StringIO BytesIO
from io import BytesIO
# 例項化io
buf = BytesIO()
# 寫入到記憶體
for i in f.chunks():
buf.write(i)
# 調整指標到開頭
buf.seek(0)
# 上傳
filename = get_unique_str() + "." + f.name.split(".")[-1]
bucket.put_object(filename, buf.getvalue())
print(filename)
file_url = "https://" + bucket_name_host + "/" + filename
# 可以考慮把檔案存到資料庫
return HttpResponse(file_url)
StringIO
在記憶體的緩衝中 操作資料 和操作檔案是類似的 也有指標的概念
驗證碼
pip install Pillow
需要:畫布 畫筆 和字型
def get_confirm_code(req):
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
# 例項化一個畫布
img_size = (150,70)
img_color = get_random_color()
img = Image.new("RGB", img_size, img_color)
# 例項化一個畫筆
draw = ImageDraw.Draw(img)
code_xy = (20, 20)
# code_color = (0, 255, 0)
# 例項化一個字型
font_path = os.path.join(settings.STATICFILES_DIRS[0], "fonts/ADOBEARABIC-BOLD.OTF")
font_size = 30
font = ImageFont.truetype(font_path, font_size)
# 畫一個字母
# draw.text(code_xy,"L", font=font, fill=code_color)
# draw.text(code_xy, "O", font=font, fill=code_color)
source = "zxcvbnmasdfghjklqwertyuiop1234567890ZXCVBNMASDFGHJKLQWERTYUIOP"
# 用來儲存 我們生成的隨機字元
res = ""
for i in range(4):
# 隨機出一個字母
code_color = get_random_color()
index = random.randint(0, len(source))
my_str = source[index]
res += my_str
draw.text((20+30*i, 20), my_str, fill=code_color, font=font)
# 畫點
for i in range(100):
x = random.randint(0, 150)
y = random.randint(0, 70)
draw.point((x, y), fill=get_random_color())
# width = random.randint(0, 100)
# draw.line((20, 65), fill=(255, 255, 255), width=50)
buf = BytesIO()
# 儲存
img.save(buf, "png")
del draw
# 儲存的session
req.session["verify_code"] = res
return HttpResponse(buf.getvalue(), content_type="image/png")
應用
def my_login_v1(req):
if req.method == "GET":
return render(req, "my_login.html")
else:
code = req.POST.get("code")
server_code = req.session.get("verify_code")
# 將使用者傳入的和系統session儲存的字元都轉小寫 然後做比較
if code and len(code) > 0 and code.lower() == server_code.lower():
return HttpResponse("ok")
else:
return HttpResponse("no ok")
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js"></script>
<script>
$(function () {
$("#myimg").click(function () {
console.log("呼叫")
$(this).attr("src", "/t06/img" + Math.random());
})
})
</script>
</head>
<body>
<form action="/t06/my_login" method="post">
{% csrf_token %}
<img src="/t06/img" alt="" id="myimg">
<br>
<input type="text" name="code" placeholder="請輸入驗證碼(忽略大小寫)">
<br>
<input type="submit" value="驗證">
</form>
</body>
</html>