登陸認證示例

用戶登陸認證

問題1:有些 API 須要用戶登陸成功以後才能訪問,有些無需登陸就能訪問python

models.py數據庫

from django.db import models

class UerInfo(models.Model):
    user_type_choices = (
        (1, '普通用戶'),
        (2, 'VIP'),
        (3, 'SVIP'),
    )
    user_type = models.IntegerField(choices=user_type_choices)
    username = models.CharField(max_length=32, unique=True)
    password = models.CharField(max_length=64)


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

登陸

urls.pydjango

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/v1/auth/$', views.AuthView.as_view()),
]

views.pyapi

from django.http import JsonResponse
from rest_framework.views import APIView
from api import models


def md5(user):
    import hashlib
    import time

    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 post(self, request, *args, **kwargs):

        ret = {'code': 1000, 'msg': None}
        try:
            user = request._request.POST.get('username')
            pwd = request._request.POST.get('password')
            obj = models.UerInfo.objects.filter(username=user, password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用戶名或密碼錯誤'
            # 爲登陸用戶建立token
            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)

解決:(認證組件的基本使用)post

  • 建立兩張表
  • 用戶登陸(返回 token 並保存到數據庫)

認證

urls.pyurl

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/v1/auth/$', views.AuthView.as_view()),
    url(r'^api/v1/order/$', views.OrderView.as_view()),
]

views.pyrest

class Authentication(object):
    def authenticate(self, request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')
        # 在rest framework內部會將這兩個字段賦值給request, 以供後續操做使用
        return (token_obj.user, token_obj)

    def authenticate_header(self, request):
        pass


class OrderView(APIView):
    '''
    訂單相關業務
    '''
    authentication_classes = [Authentication, ]

    def get(self, request, *args, **kwargs):
        token = request._request.GET.get('token')
        if not token:
            return HttpResponse('用戶未登陸')
        ret = {'code': 1000, 'msg': None, 'data': None}
        try:
            ret['data'] = ORDER_DICT
        except Exception as e:
            pass
        return JsonResponse(ret)

這樣寫有一個很差之處,在每個業務中,都須要添加 authentication_classes = [Authentication, ] 作相關認證,所以能夠把它設置爲全局code

須要在 settings.py 中添加token

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.auth.FirstAuthentication', 'api.utils.auth.Authentication']
}

在 api 下新建 utlis,utils中新建 auth.pymd5

# -*- coding: utf-8 -*-
from rest_framework import exceptions
from api import models
from rest_framework.authentication import BaseAuthentication


class FirstAuthentication(BaseAuthentication):
    def authenticate(self, request):
        pass

    def authenticate_header(self, request):
        pass


class Authentication(BaseAuthentication):
    def authenticate(self, request):
        token = request._request.GET.get('token')
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')
        # 在rest framework內部會將這兩個字段賦值給request, 以供後續操做使用
        return (token_obj.user, token_obj)

    def authenticate_header(self, request):
        pass

views.py

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView
from api import models

ORDER_DICT = {
    1: {
        'name': 'qiu',
        'age': 18,
        'gender': '男',
        'content': '...'
    },

    2: {
        'name': 'xi',
        'age': 19,
        'gender': '男',
        'content': '.....'
    }
}


def md5(user):
    import hashlib
    import time

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

    authentication_classes = [] 

    def post(self, request, *args, **kwargs):

        ret = {'code': 1000, 'msg': None}
        try:
            user = request._request.POST.get('username')
            pwd = request._request.POST.get('password')
            obj = models.UerInfo.objects.filter(username=user, password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用戶名或密碼錯誤'
            # 爲登陸用戶建立token
            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 = [FirstAuthentication, Authentication, ]

    def get(self, request, *args, **kwargs):
        token = request._request.GET.get('token')
        if not token:
            return HttpResponse('用戶未登陸')
        ret = {'code': 1000, 'msg': None, 'data': None}
        try:
            ret['data'] = ORDER_DICT
        except Exception as e:
            pass
        return JsonResponse(ret)


class UserInfoView(APIView):
    '''
    用戶中心
    '''

    def get(self, request, *args, **kwargs):
        return HttpResponse('用戶信息')

這樣一來,全部的業務都添加了認證,當某一個不須要此認證時,只需將 authentication_classes 設置爲空列表便可

若是是匿名用戶,能夠將其設置爲 None

setting.py

REST_FRAMEWORK = {
    'UNAUTHENTICATED_USER': None,   # 匿名,request.user = None
    'UNAUTHENTICATED_TOKEN': None   # 匿名,request.auth = None
}
相關文章
相關標籤/搜索