zoukankan      html  css  js  c++  java
  • 登录认证示例

    用户登录认证

    问题1:有些 API 需要用户登录成功之后才能访问,有些无需登录就能访问

    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.py

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

    views.py

    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)
    
    

    解决:(认证组件的基本使用)

    • 创建两张表
    • 用户登录(返回 token 并保存到数据库)

    认证

    urls.py

    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.py

    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, ] 做相关认证,因此可以把它设置为全局

    需要在 settings.py 中添加

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

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

    # -*- 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
    }
    
  • 相关阅读:
    [Leetcode] Longest Substring Without Repeating Characters
    [Leetcode] Clone Graph
    [Leetcode] LRU Cache
    行转列
    微信 Demo
    微信开发-step by stemp
    知识库
    SSAS GUID 添加 行计数,非重复计数 等 遇到的莫名其妙的问题
    javascript 前段MVVM 框架
    微信接口开发
  • 原文地址:https://www.cnblogs.com/qiuxirufeng/p/10432886.html
Copyright © 2011-2022 走看看