Drf之局部认证和全局认证(六)

登录的token操作

# app.models.py:表结构
class User(models.Model):
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

class UserToken(models.Model):
    token = models.CharField(max_length=64)
    user = models.OneToOneField(to='User')
    
    
# app.objson.py:序列化模块
from rest_framework import serializers
from app import models
class UserJson(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = '__all__'

        
# app.views.py      
from rest_framework.views import APIView
from rest_framework.response import Response
from app import common, models, objson
class Login(APIView):
    def post(self, request):
        # 用前台提交的数据完成数据库查询校验
        data_dic = request.data
        user = models.User.objects.filter(**data_dic).first()
        
        if user:
            # 登录成功操作token
            token = common.get_token()
            # token的数据库操作,第一次产生token是新建,再次就是更新
            models.UserToken.objects.update_or_create(user=user, defaults={"token": token})
            user_data = objson.UserJson(user).data
            return Response({
                "status": 0,
                "msg": 'login success',
                "token": token,  # 将token返回给前台
                "results": user_data
            })
        return Response({
            "status": 1,
            "msg": 'login failed'
        })

认证方法的实现

# 源码分析
# as_view() => APIView.dispatch => self.initial(request, *args, **kwargs) => 封装后的drf的request => request.user => self._authenticate() => authenticate(self, request) 的源码根据地

# app.views.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class LoginAuthenticate(BaseAuthentication):
    def authenticate(self, request):
        # 登录逻辑:如果用户登录了,登录操作产生了token,且前后台同步了
        # 登录判断:再次发生的请求,没有token代表没登录,错误token,代表无效的登录,token正确才是正常的登录用户
        # 如何将token取出, 规定token用请求头传递
        token = request.META.get('HTTP_TOKEN')
        result = models.UserToken.objects.filter(token=token).first()
        if result:
            # 认证通过,可以返回None (有多个认证时),可以返回两个值:user,auth,源码中可以看到必须返回user,后面的值可以返回token(单独token认证)、auth(多认证)或者None(认证不通过)
            return result.user, token
        else:
            # 验证失败,抛出APIException或其子类对象
            raise AuthenticationFailed("认证失败")
            
class Books(APIView):
    authentication_classes = [LoginAuthenticate]
    # 视图函数处理的逻辑
    def get(self, request):
        # 通过认证后,用request.user拿到当前登录的用户,用request.auth拿到认证值(该值通常自定义)
        print(request.user)
        return Response({
            "status": 0,
            "msg": 'ok',
            "results": []
        })

局部认证

# app.auth.py 完成校验的所有逻辑
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app import models
class LoginAuthenticate(BaseAuthentication):
    def authenticate(self, request):
        token = request.META.get('HTTP_TOKEN')
        result = models.UserToken.objects.filter(token=token).first()
        if result:
            return result.user, token
        else:
            raise AuthenticationFailed("认证失败")
            
# 局部认证: 在需要认证的类上方标注认证类:authentication_classes = [auth1, ... authn]
from app import auth
class Books(APIView):
    authentication_classes = [auth.LoginAuthenticate]
    def get(self, request):
        print(request.user)
        return Response({
            "status": 0,
            "msg": 'ok',
            "results": []
        })

# 案例:访问当前登录用户信息 - 个人主页
class Home(APIView):
	# 添加登录认证即可
    authentication_classes = [auth.LoginAuthenticate]
    def get(self, request):
        return Response({
            "status": 0,
            "msg": 'ok',
            "results": objson.UserJson(request.user).data
        })

全局认证

# 1.在settings.py中配置
# 全局认证
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'app.auth.LoginAuthenticate'
    ),
}

# 2.所有的CBV类都不需要添加类属性:authentication_classes

# 局部禁用
# 3.在不需要认证的CBV类中添加类属性:authentication_classes = []



注销:在全局认证情况下

class Logout(APIView):
    # 在全局认证情况下,如果能走get方法,代表已经通过登录认证(登录状态),就可以注销
    def get(self, request):
        models.UserToken.objects.update_or_create(user=request.user, defaults={'token': common.get_token()})
        return Response({
            "status": 0,
            "msg": 'logout success',
        })

补充:前台操作cookie

<body>
<button class="login">登录请求</button>
<button class="token">获取token</button>
</body>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script>
    $('.login').click(function () {
        token = '88888';
        $.cookie('qt', '前台操作cookie');
        $.cookie('token', token);
    });

    $('.token').click(function () {
        alert($.cookie('token'))
    })
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值