python Django framework框架(二十四)之认证

三大认证组件

认证组件

1、authentication

"""
系统:session认证
rest_framework.authentication.SessionAuthentication
ajax请求通过认证:
cookie中要携带 sessionid、csrftoken,请求头中要携带 x-csrftoken

第三方:jwt认证 
rest_framework_jwt.authentication.JSONWebTokenAuthentication
ajax请求通过认证:
请求头中要携带 authorization,值为 jwt空格token

自定义:基于jwt、其它
1)自定义认证类,继承BaseAuthentication(或其子类),重写authenticate
2)authenticate中完成
	拿到认证标识 auth
	反解析出用户 user
	前两步操作失败 返回None => 游客
	前两步操作成功 返回user,auth => 登录用户
	注:如果在某个分支抛出异常,直接定义失败 => 非法用户
"""

2、自定义认证类:基于jwt

from rest_framework.exceptions import AuthenticationFailed
import jwt
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
from rest_framework_jwt.authentication import jwt_decode_handler

 

3、普通自定义认证类

from rest_framework.authentication import BaseAuthentication
def authenticate(self, request):
    auth = 从request中得到
    user = 从auth中得到
    if not user:
        return None
    return user, auth

权限组件

1、permission

"""
系统:
1)AllowAny:允许所有用户,校验方法直接返回True
2)IsAuthenticated:只允许登录用户
	必须request.user和request.user.is_authenticated都通过
3)IsAuthenticatedOrReadOnly:游客只读,登录用户无限制
	get、option、head 请求无限制
	前台请求必须校验 request.user和request.user.is_authenticated
4)IsAdminUser:是否是后台用户
	校验 request.user和request.user.is_staff    is_staff(可以登录后台管理系统的用户)
	

自定义:基于auth的Group与Permission表
1)自定义权限类,继承BasePermission,重写has_permission
2)has_permission中完成
	拿到登录用户 user <= request.user
	校验user的分组或是权限
	前两步操作失败 返回False => 无权限
	前两步操作成功 返回True => 有权限
"""

2、自定义权限类:为 管理员 分组成员

from rest_framework.permissions import BasePermission

class AdminPermission(BasePermission):
    # 继承BasePermission,重写has_permission
    def has_permission(self, request, view):
        # 有权限,返回True
        # 无权限,返回False
        user = request.user
        if not user:
            return False
        # 用户是 管理员 分组 (管理员分组是Group表中的一条自定义记录)
        if not user.groups.filter(name='管理员'):
            return False
        # 登录的用户必须是自定义管理员分组成员
        return True

频率组件

1、throttle

"""
系统:
1)AnonRateThrottle:对同一IP游客的限制
2)UserRateThrottle:对同一IP登录用户的限制
必须在settings.py中
'DEFAULT_THROTTLE_RATES': {
    'user': '10/min',  # 登录的用户一分钟可以访问10次
    'anon': '3/min',  # 游客一分钟可以访问3次
}
在视图类中:
class TempAPIView(APIView):
	...
	throttle_classes = [AnonRateThrottle, UserRateThrottle]
	
	

自定义:基于auth的Group与Permission表
1)自定义频率类,继承SimpleRateThrottle,重写get_cache_key,明确scope
	SimpleRateThrottle已经帮我们实现了 allow_request、wait
2)scope与settings.py的DEFAULT_THROTTLE_RATES配合使用
3)get_cache_key中完成
	拿到限制信息 ident <= request中获取
	没有限制信息 返回None => 不限制
	有限制信息 返回限制信息字符串 => 有限制
"""

2、自定义频率类:一分钟一个手机号只允许访问一次接口

from rest_framework.throttling import SimpleRateThrottle

class ThreeMinRateThrottle(SimpleRateThrottle):
    scope = 'sms'
    def get_cache_key(self, request, view):
        # 对手机号频率限制
        ident = request.data.get('mobile')
        if not ident:  # 为发现限制条件,返回None代表不进行频率限制
            return None
        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }
# settings.py
'DEFAULT_THROTTLE_RATES': {
    'user': '10/min',  # 登录的用户一分钟可以访问10次
    'anon': '3/min',  # 游客一分钟可以访问3次
    'sms': '1/min',
}

jwt认证

JWT

1、工作原理

"""
1) jwt = base64(头部).base(载荷).hash256(base64(头部).base(载荷).密钥)
2) base64是可逆的算法、hash256是不可逆的算法
3) 密钥是固定的字符串,保存在服务器
"""

2、drf-jwt

官网
http://getblimp.github.io/django-rest-framework-jwt/
安装子:虚拟环境
pip install djangorestframework-jwt
使用:user/urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path('login/', obtain_jwt_token),
]
测试接口:post请求
"""
postman发生post请求

接口:http://api.luffy.cn:8000/user/login/

数据:
{
	"username":"admin",
	"password":"admin"
}
"""

3、drf-jwt开发

配置信息:JWT_AUTH到dev.py中
import datetime
JWT_AUTH = {
    # 过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 自定义认证结果:见下方序列化user和自定义response
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',  
}
序列化user:user/serializers.py(自己创建)
from rest_framework import serializers
from . import models
class UserModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['username']
自定义response:user/utils.py
from .serializers import UserModelSerializers
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 0,
        'msg': 'ok',
        'data': {
            'token': token,
            'user': UserModelSerializers(user).data
        }
    }
基于drf-jwt的全局认证:user/authentications.py(自己创建)
import jwt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework_jwt.authentication import get_authorization_header
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication

class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
    def authenticate(self, request):
        jwt_value = get_authorization_header(request)

        if not jwt_value:
            raise AuthenticationFailed('Authorization 字段是必须的')
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('签名过期')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('非法用户')
        user = self.authenticate_credentials(payload)

        return user, jwt_value
全局启用:settings/dev.py
REST_FRAMEWORK = {
    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'user.authentications.JSONWebTokenAuthentication',
    ),
}
局部启用禁用:任何一个cbv类首行
# 局部禁用
authentication_classes = []

# 局部启用
from user.authentications import JSONWebTokenAuthentication
authentication_classes = [JSONWebTokenAuthentication]
多方式登录:user/utils.py
import re
from .models import User
from django.contrib.auth.backends import ModelBackend
class JWTModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            else:
                user = User.objects.get(username=username)
        except User.DoesNotExist:
            return None
        if user.check_password(password) and self.user_can_authenticate(user):
            return user
配置多方式登录:settings/dev.py
AUTHENTICATION_BACKENDS = ['user.utils.JWTModelBackend']
手动签发JWT:了解 - 可以拥有原生登录基于Model类user对象签发JWT
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值