Django身份认证示例

181 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

一、简单认证示例

场景:用户查看自己购买的订单,需登陆验证

以下是demo:

models.py
from django.db import models

class UserInfo(models.Model):
    user_type_choice = (
        (1,"普通用户"),
        (2,"会员"),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    username = models.CharField(max_length=32,unique=True)
    password = models.CharField(max_length=64)


class UserToken(models.Model):
    user = models.OneToOneField(to=UserInfo)
    token = models.CharField(max_length=64)

认证url(urls.py)

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [

    url(r'^api/v1/auth', views.AuthView.as_view()),
    url(r'^api/v1/order', views.OrderView.as_view()),
]

views.py

from django.shortcuts import  HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
from . import models
from rest_framework import exceptions
import hashlib
import time


class Authentication(BaseAuthentication):
    """
    认证类
    """def authenticate(self, request):
        token = request._request.GET.get("token")
        toke_obj = models.UserToken.objects.filter(token=token).first()
        if not toke_obj:
            raise exceptions.AuthenticationFailed("用户认证失败")
        return (toke_obj.user, toke_obj)  # 这里返回值一次给request.user,request.authdef authenticate_header(self, val):
        passdef md5(user):
    ctime = str(time.time())
    m = hashlib.md5(bytes(user,encoding="utf-8"))
    m.update(bytes(ctime,encoding="utf-8"))
    return m.hexdigest()

class AuthView(APIView):
    """登陆认证"""def dispatch(self, request, *args, **kwargs):
        return super(AuthView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return HttpResponse('get')

    def post(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': "登录成功"}
        try:
            user = request._request.POST.get("username")
            pwd = request._request.POST.get("password")
            obj = models.UserInfo.objects.filter(username=user, password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = "用户名或密码错误"else:
                token = md5(user)
                models.UserToken.objects.update_or_create(user=obj, defaults={"token": token})
                ret['token'] = token

        except Exception as e:
            ret['code'] = 1002
            ret['msg'] = "请求异常"return JsonResponse(ret)



class OrderView(APIView):
    '''查看订单'''

    authentication_classes = [Authentication,]    #添加认证def get(self,request,*args,**kwargs):
        #request.user#request.auth
        ret = {'code':1000,'msg':"你的订单已经完成",'data':"买了一个mac"}
        return JsonResponse(ret,safe=True)

用户使用token访问,不带token或token错误会认证错误。

http://127.0.0.1:8000/api/v1/order?token=63743076dfaefa632f6acb302cf90400

###返回结果
{"code": 1000, "msg": "\u4f60\u7684\u8ba2\u5355\u5df2\u7ecf\u5b8c\u6210", "data": "\u4e70\u4e86\u4e00\u4e2amac"}

对于以上demo可能会有疑问为什么添加了authentication_classes认证类列表就会使用我们自己定义的认证类,后续会从源码角度分析原因。