Python3+Django2的Authorization Token验证

转载请著名出处:https://blog.csdn.net/qq_32506429/article/details/89641123

初学Python Web,环境是python3 +Django2,然后Web想做简单的用户token验证,验证通过才能进行其他操作;在网上找了好久,先学了装饰器,才看懂很多教程,但是没有直接上代码的,对伸手党的我很不友好(>.<羞耻...),所以研究了一天后决定写一篇博客,好了不废话,上干货。

第一步:引入pyjwt:

pip3 install pyjwt

第二步:在models里建立自己的用户类 Member

from django.db import models
from DjangoUeditor.models import UEditorField
import jwt
from InterviewQA import settings
import datetime


class Member(models.Model):
    username = models.CharField(max_length=11, verbose_name='用户名')
    password = models.CharField(max_length=48, verbose_name='密码')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='添加时间')
    phone = models.CharField(max_length=11, verbose_name='手机号')
    account_type_choice = ((1, "普通会员"), (2, "高级会员"), (3, "企业普通会员"),
                           (4, "企业高级会员"))
    account_type = models.IntegerField(choices=account_type_choice, default=1,
                                       verbose_name='账号类型')
    age = models.IntegerField(default=0, verbose_name='年龄')
    birthday = models.DateField(verbose_name='生日', auto_now=True, blank=True)
    update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间', blank=True, null=True)
    #real_name = models.OneToOneField("RealName", on_delete=models.SET_NULL, null=True, blank=True)
    nick_name = models.CharField(max_length=24, verbose_name='昵称', default="新用户")
    login_time = models.DateTimeField(verbose_name='登录时间', auto_now=True, blank=True)
    last_login_time = models.DateTimeField(verbose_name='上次登录时间', auto_now=False, blank=True,
                                           default=datetime.datetime.utcnow())
    vip_start_time = models.DateTimeField(verbose_name='会员开始时间', auto_now=True, blank=True)
    vip_end_time = models.DateTimeField(verbose_name='会员结束时间', auto_now=True, blank=True)
    account_status_choice = ((1, "正常"), (2, "冻结"), (3, "删除"))
    account_status = models.IntegerField(choices=account_status_choice, default=1,
                                         verbose_name='账户状态')
    email = models.EmailField(verbose_name='邮箱', blank=True)
    QQ = models.CharField(max_length=24, verbose_name='QQ', blank=True)
    WeChart = models.CharField(max_length=32, verbose_name='微信', blank=True)
    sign = models.CharField(max_length=32, verbose_name='签名', blank=True)
    balance = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='余额', blank=True, default=0.00)
    integral = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='积分', blank=True, default=0.00)
    head = models.ImageField(upload_to="head", default='head/7d9d46ae3c9edc877151647bf9c6560020190422165247_90.jpg',
                             verbose_name='头像', null=True, blank=True)

    exp_time = models.DateTimeField(verbose_name='Token过期时间', auto_now=False, blank=True,
                                    default=datetime.datetime.utcnow() + datetime.timedelta(days=1))

    def __str__(self):
        return self.nick_name

    @property
    def token(self):
        return self._generate_jwt_token()

    def _generate_jwt_token(self):
        exp = datetime.datetime.utcnow() + datetime.timedelta(days=1)
        token = jwt.encode({
            'exp': exp,
            'iat': datetime.datetime.utcnow(),
            'data': {
                'username': self.username
            }
        }, settings.SECRET_KEY, algorithm='HS256')
        lt = self.login_time
        nt = datetime.datetime.utcnow()
        # print("exp=", exp)
        self.exp_time = exp
        self.last_login_time = lt
        self.login_time = nt
        self.save()
        return token.decode('utf-8')

    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户' 

第三步:创建验证token的装饰器

from django.conf import settings
from django.http import JsonResponse
from django.core.exceptions import PermissionDenied
import jwt

# 引入自己建的数据库model类
from app.models import Member


def auth_permission_required(perm):
    def decorator(view_func):
        def _wrapped_view(request, *args, **kwargs):
            # 格式化权限
            perms = (perm,) if isinstance(perm, str) else perm

            if request.user.is_authenticated:
                # 正常登录用户判断是否有权限
                if not request.user.has_perms(perms):
                    raise PermissionDenied
            else:
                try:
                    auth = request.META.get('HTTP_AUTHORIZATION').split()
                except AttributeError:
                    return JsonResponse({'status': 0, 'err': '缺少参数Token'})
                    # return JsonResponse({"code": 401, "message": "No authenticate header"})

                # 用户通过API获取数据验证流程
                if auth[0].lower() == 'token':
                    try:
                        dict = jwt.decode(auth[1], settings.SECRET_KEY, algorithms=['HS256'])
                        username = dict.get('data').get('username')
                    except jwt.ExpiredSignatureError:
                        return JsonResponse({'status': 0, 'err': 'Token已过期'})
                        # return JsonResponse({"status_code": 401, "message": "Token expired"})
                    except jwt.InvalidTokenError:
                        return JsonResponse({'status': 0, 'err': '无效的Token'})
                    except Exception as e:
                        return JsonResponse({'status': 0, 'err': '获取用户失败'})

                    try:
                        user = Member.objects.get(username=username)
                    except Member.DoesNotExist:
                        return JsonResponse({'status': 0, 'err': "用户不存在"})

                    if user.account_status != 1:
                        return JsonResponse({'status': 0, 'err': "账户异常"})

                    # # Token登录的用户判断是否有权限
                    # if not user.has_perms(perms):
                    #     return JsonResponse({'status': 0, 'err': "未授权用户,被拒绝访问"})
                else:
                    return JsonResponse({'status': 0, 'err': "不支持身份验证类型"})

            return view_func(request, *args, **kwargs)

        return _wrapped_view

    return decorator


def get_user(req):
    auth = req.META.get('HTTP_AUTHORIZATION').split()
    dict = jwt.decode(auth[1], settings.SECRET_KEY, algorithms=['HS256'])
    username = dict.get('data').get('username')
    try:
        user = Member.objects.get(username=username)
    except Member.DoesNotExist:
        return JsonResponse({'status': 0, 'err': "用户不存在"})

    return user
 

第四步:登录获取token

 

from app.models import Member
#登录
def login(req):
    res = {'status': 1, 'err': '',
           'data': {'is_success': False, "token": "",
                    'last_login_time': '', 'login_time': '', 'exp_time': ''}}
    if req.method == 'POST':
        phone = req.POST.get("phone")
        pwd = req.POST.get("password")
        print(phone, pwd)
        if not phone:
            res["err"] = "请输入手机号"
            return json_response(res)
        if not pwd:
            res["err"] = "请输入密码"
            return json_response(res)
        try:
            user = Member.objects.get(username=phone)
        except Member.DoesNotExist:
            res["err"] = "用户不存在"
            return json_response(res)

        if user:
            if user.account_status == 1:
                print(user.nick_name)
                p = sha1_encode(pwd)
                if p != user.password:
                    res["err"] = "用户名密码错误"
                    return json_response(res)
                else:
                    res["msg"] = "登录成功"
                    res["data"]["is_success"] = True
                    #调用user.token会创建token
                    res["data"]["token"] = user.token
                    res["data"]["last_login_time"] = user.last_login_time
                    res["data"]["login_time"] = user.login_time
                    res["data"]["exp_time"] = user.exp_time
                    return json_response(res)
            res["err"] = "用户不存在"
            return json_response(res)
        else:
            res["err"] = "用户不存在"
            return json_response(res)

    else:
        res["err"] = "请求方式错误"
        return json_response(res) 

 

第五步:用token获取用户信息、通过token修改用户信息等等

from app.decorator.UserAuth import auth_permission_required, get_user
from app.models import Member
# token验证装饰器
@auth_permission_required('account.select_user')
def info(req):
    res = {'status': 1, 'err': '', 'data': {}}
    if req.method == 'GET':
        user = get_user(req)

        res['data']["username"] = user.username
        res['data']["phone"] = user.phone
        res['data']["account_type"] = user.account_type
        res['data']["age"] = user.age
        res['data']["birthday"] = user.birthday
        res['data']["real_name"] = user.real_name
        res['data']["nick_name"] = user.nick_name
        res['data']["account_status"] = user.account_status
        res['data']["email"] = user.email
        res['data']["QQ"] = user.QQ
        res['data']["WeChart"] = user.WeChart
        res['data']["sign"] = user.sign
        res['data']["balance"] = user.balance
        res['data']["integral"] = user.integral
        res['data']["head"] = settings.HTTP_PORT + user.head.url
        return json_response(res)
    res["err"] = "请求方式错误"
    return json_response(res)

 

# token验证装饰器
@auth_permission_required('account.change_user')
def update(req):
    res = {'status': 1, 'err': '', 'data': {'is_success': False}}
    if req.method == 'POST':
        nick_name = req.POST.get("nickname")
        phone = req.POST.get("phone")
        head = req.POST.get("head")
        QQ = req.POST.get("QQ")
        email = req.POST.get("email")
        WeChart = req.POST.get("WeChart")
        sign = req.POST.get("sign")
        birthday = req.POST.get("birthday")

        user = get_user(req)

        try:
            with transaction.atomic():
                if phone:
                    user.username = phone
                    user.phone = phone
                if nick_name:
                    user.nick_name = nick_name
                if head:
                    user.head = head
                if QQ:
                    user.QQ = QQ
                if email:
                    user.email = email
                if WeChart:
                    user.WeChart = WeChart
                if sign:
                    user.sign = sign
                if birthday:
                    user.birthday = birthday

                user.update_time = datetime.datetime.utcnow()
                user.save()

                res["msg"] = "修改成功"
                res["data"]["is_success"] = True
                return json_response(res)

        except Exception as e:
            print(e)
            res["err"] = "修改失败"
            return json_response(res)

    else:
        res["err"] = "请求方式错误"
        return json_response(res)

 

登录:

Python3+Django2的Authorization Token验证_第1张图片 登录获取token

 

获取用户信息:header里添加Authorization  值为"Token  登录时返回的token" ;"Token"后有个空格;

 

Python3+Django2的Authorization Token验证_第2张图片

 

用token修改用户信息:

Python3+Django2的Authorization Token验证_第3张图片

 

修改前:

Python3+Django2的Authorization Token验证_第4张图片

 

修改后:

Python3+Django2的Authorization Token验证_第5张图片

 

参考资料:https://www.jb51.net/article/155177.htm 

你可能感兴趣的:(Python)