自定义用户和认证 中间件 文件上传/oss 图片验证码

自定义用户

写一个继承自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' # 目录名.文件名.类名
]

上传文件

在models.py

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")

views.py

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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wufucks

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值