认证:(auth | authentication)
REST framework
提供了一些开箱即用的身份验证方案,并且还允许你实现自定义方案。
在 rest_framework.authentication
中 查看 认真方案
方案的 基类from rest_framework.authentication import BaseAuthentication
- 基于用户名密码的 认证
BasicAuthentication(BaseAuthentication)
- 基于Session的认证
SessionAuthentication(BaseAuthentication)
- 基于Token 的认证
TokenAuthentication(BaseAuthentication)
- 基于远程用户的认证(专用用户管理服务器)
RemoteUserAuthentication(BaseAuthentication)
认证的流程
rest_framework 中的
在APIView 的 dispatch() 方法 执行 了 和 普通djando 不一样的方法
self.initial(request,*,**)
方法 中 添加了新动作 (版本号的获取,认证,权限,频率限制)顺序 先认证 再权限 再限制
认证
self.perform_authentiction(request)
权限
self.check_permissions(request)
限制
self.check_throttles(request)
自定义认证 token
- 创建一个APP 将所有的 版本控制 认证 权限 与 主业务 区分开
定义一个类继承 BaseAuthentication
基于Token的认证
注意:
不做认证 就不会有 request.user 个人用户信息
- 重写 authenticte() 方法 通过 request.query_params.get('token') 获取 token 参数
- 通过认证必须返回两个参数 第一个是用户的 queryset 对象 第二个是token 值 元组的形式
错误或异常 需要抛出
AuthenticationFailed
错误
- # 所有 认证 的 父类
- from rest_framework.authentication import BaseAuthentication
- from auth_demo import models
- # 不通过认证 需要抛出的 字段错误
- from rest_framework.exceptions import AuthenticationFailed
-
- class LoginAuth(BaseAuthentication):
-
- 重写父类的 authenticte 方法 认证信息携带在 params 路由参数中
- def authenticate(self, request):
-
- token = request.query_params.get('token')
- if token:
- # 如果请求的URL中携带了token参数
- user_obj = models.UserInfo.objects.filter(token=token).first()
- if user_obj:
- # token是有效的
- return user_obj, token # request.user, request.auth
- else:
- raise AuthenticationFailed('无效的token')
- else:
- raise AuthenticationFailed('请求的URL中必须携带token参数')
-
操作流程:
创建用户表 认证登录操作 最好额外创建APP
- from django.db import models
- class UserInfo(models.Model):
- name = models.CharField(max_length=32)
- pwd = models.CharField(max_length=32)
- # token 设置为可以为空 查询时可以为空的字段 有时注册了但没有登录
- token = models.CharField(max_length=128, null=True, blank=True)
创建 注册需要的 接口
127.0.0.1:8000/user/register/
- # 一级路由
- from django.conf.urls import url, include
- urlpatterns = [
- url(r'^users/', include('auth_demo.urls')),
- ]
- # 二级路由
- from django.conf.urls import url, include
- from auth_demo import views
- urlpatterns = [
- url(r'^register/$', views.RegisterView.as_View()),
- ]
创建注册的视图类 Register
- from rest_framework.views import APIView
- from rest_framework.response import Response
- from auth_demo import models
- class RegisterView(APIView):
- ''' 注册用户的试图 只提供 post 请求 '''
- def post(self, request):
- # 获取 用户名密码
- name, pwd = request.data.get('name'), request.data.get('pwd')
- # 可以做一些 账号密码的 限制
- if name and pwd:
- models.UserInfo.objects.create(name=name,pwd=pwd)
- return Response('创建成功')
- else:
- return Response('无效的参数')
登录之后使用
uuid.uuid1().hex
生成token 保存到数据库中使用 update_or_create 方法 有就更新 没有就新增
- class LoginView(APIView):
- def post(self, request):
- name = request.data.get('name')
- pwd = request.data.get('pwd')
- if name and pwd:
- user_obj = models.UserInfo.objects.filter(name=name, pwd=pwd).first()
- if user_obj:
- # 登陆成功
- # 生成token(时间戳 + Mac地址)
- token = uuid.uuid1().hex
- # 1.保存在用户表中
- user_obj.token = token
- user_obj.save()
- # 2.给用户返回
- return Response({'error_no': 0, 'token': token})
- else:
- # 用户名或密码错误 通过 error_no 来判断请求是否成功
- return Response({'error_no': 1, 'error': '用户名或密码错误'})
- else:
- return Response('无效的参数')
将认证的 类添加到 配置项中
全局配置
'- # 后面的 权限 是基于 认证的 所以全局一定要配置 权限
- REST_FRAMEWORK = {
- # 自定义的 认证
- # 'DEFAULT_AUTHENTICATION_CLASSES': ['auth_demo.auth.MyAuth', ],
- # 使用 rest_framework 给出的认证
- # 'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentiction.TokenAuthentication', ]
- # 限制比较宽松的认证
- 'DEFAULT_AUTHENTICTION_CLASSES': []
- }
运行局部配置
- # 写在单独的试图中
- authentication_classes = [MyAuth, ]