DRF框架之认证、授权和登录

一、认证

1.Browsable API页面认证与JWT认证比较

1.Browsable API页面认证

  • 指定permission_classes
  • 添加rest_framework.urls路由

2.Json Web Token认证

  • 最常用的认证方式
    • Session认证
    • Token认证
  • Session认证
    • 保存在服务端,增加服务器开销
    • 分布式架构中,难以维持Session会话同步
    • CSRF攻击风险
  • Token认证
    • 保存在客户端
    • 跨语言、跨平台
    • 拓展性强
    • 鉴权性能高
  • JWT
    • 由三部分组成
      • header、playload、signature
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhemF6aWUiLCJhdWQiOiJ1c2VycyIsImlhdCI6MTU5NTY3NTA1NiwiZXhwIjoxNTk2Mjc5ODU2LCJ1c2VyX2lkIjozMDI3NTQxfQ.vJPcwpw4_WBLGBkXO3SUPbyfgDzk4S3FwWzJrCtvhwA
    • header
      • 声明类型
      • 声明加密算法,默认为HS256
      • base64加密,可以解密
    • playload
      • 存放过期时间、签发用户等
      • 可以添加用户的非敏感信息
      • base64加密,可以解密
    • signature
      • 有三部分组成
      • 使用base64加密之后的header+.+使用base64加密之后的playload+.+使用HS256算法加密,同时secret加盐处理

2.Browsable API页面认证

1.源码

'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    ]

2.说明

BasicAuthentication:基本的用户密码认证

SessionAuthentication:session会话认证

SessionAuthentication和BasicAuthentication二者缺一不可,相辅相成,我们也可以在此基础上增加别的认证,如:token认证、微信/QQ第三方认证、LADP认证

在authentication.py模块中,除了上面这两种,还有其它的认证方式可供选择:

3.指定视图下认证

authenticcation_classes = []  # 列表中添加对应的认证方式

一般不需要指定视图下进行认证,往往一个项目下只会使用一种认证方式

4.创建超级管理员

命令行

python manage.py createsuperuser --username USERNAME --email EMAIL

5.添加路由

这里提供的是一种前后端不分离的登录,后面会舍弃掉

在全局下的urls.py中添加如下代码

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('rest_framework.urls'))
]

我们可以去看看rest_framework下的urls.py

配置了之后就已经提供了登录和登出的接口

6.登录

2.JWT认证

1.jwt实现原理

1.安装jwt

pip install -i https://pypi.douban.com/simple pyjwt

2.引入jwt

import jwt

3.指定header和playload

header一般不需要指定,使用默认值即可

指定后端需要存放的一些非敏感信息

playload = {
    'username': '小公瑾',
    'age': 18
}

3.服务端创建token令牌

token = jwt.encode(playload, key='user')  # key由服务器来规定

4.服务端对前端用户传递的token进行解密

res = jwt.decode(token, key='user')

2.drf的token认证实现方法

1.安装djangorestframework-jwt

pip install -i https://pypi.douban.com/simple djangorestframework-jwt

2.全局配置指定JWT Token认证

一定要注意列表是有优先级的,需要把该认证放到第一个位置

REST_FRAMEWORK = {
    # 认证方式
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication'
    ]
}

3.根路由配置user模块

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('user/', include('user.urls'))
]

4.user子模块下添加路由

from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns = [
    path('login/', obtain_jwt_token)
]

5.验证结果

6.重写jwt_response

1).重写jwt_response_payload_handler

def jwt_response_payload_handler(token, user=None, request=None):

    return {
        'user_id': user.id,
        'username': user.username,
        'token': token
    }

2).注册重写的方法

将rest_framework_jwt中的全局配置进行覆盖,源码配置如下:

3).在全局配置中重写配置

JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER':
    'utils.jwt_handler.jwt_response_payload_handler'
}

7.验证结果

8.其它配置和说明

1).其它接口认证

  • 前端用户访问一些需要认证之后的接口,那么默认需要在请求头中携带参数
  • 请求key默认为Authorization,值为前缀+空格+token值,如:
JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhemF6aWUiLCJhdWQiOiJ1c2VycyIsImlhdCI6MTU5NTY3NTA1NiwiZXhwIjoxNTk2Mjc5ODU2LCJ1c2VyX2lkIjozMDI3NTQxfQ.vJPcwpw4_WBLGBkXO3SUPbyfgDzk4S3FwWzJrCtvhwA

2).修改token过期时间

覆盖rest_framework_jwt配置

import datetime

JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER':
    # token过期时间默认为300秒,这里可以自定义
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}

二、授权

1.源码

'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]

2.说明

源码中只提供了AllowAny的授权,它表示不限制任何权限,一般情况下,这种授权不会满足要求,我们可以看看permissions.py模块下提供的其它授权

 AllowAny:任意权限

IsAuthenticated:允许登录后拥有权限

IsAdminUser:管理员权限

IsAuthenticatedOrReadOnly:未登录下只允许浏览

3.指定视图下权限

permission_classes = [permissions.AllowAny]

permissions需要引入

from rest_framework import permissions

 

posted @ 2020-07-25 16:35  小公瑾  阅读(1307)  评论(2编辑  收藏  举报