您现在的位置是:首页 >技术杂谈 >Django实现接口自动化平台(二)认证&授权&登录【持续更新中】网站首页技术杂谈
Django实现接口自动化平台(二)认证&授权&登录【持续更新中】
上一章:
Django实现接口自动化平台(一)日志功能【持续更新中】_做测试的喵酱的博客-CSDN博客
下一章:
一、认证与授权配置
1、认证:获取权限的方式
2、授权:通过认证之后,可以获取哪些权限
通过APIVIew实现认证与授权。
APIVIew源码:
class APIView(View):
# The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
3、常用的认证机制:
- Session认证
- Token认证
Session认证特点:
- 保持在服务端,消耗服务器性能
- 分布式架构中,难以维持Session会话同步
- CSRF攻击风险
Token认证 :
- 保存在客户端
- 跨平台、跨语言
- 拓展性强
- 鉴权性能高
1.1 配置项目的认证与授权
在setting.py文件中,
REST_FRAMEWORK = {
# 指定使用的认证类
# a.在全局指定默认的认证类(指定认证方式)
'DEFAULT_AUTHENTICATION_CLASSES': [
# b.Session会话认证
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
# 指定使用的权限类
# a.在全局指定默认的权限类(当认证通过之后,可以获取何种权限)
'DEFAULT_PERMISSION_CLASSES': [
# AllowAny不管是否有认证成功,都能获取所有权限
# IsAdminUser管理员(管理员需要登录)具备所有权限
# IsAuthenticated只要登录,就具备所有权限
# IsAuthenticatedOrReadOnly,如果登录了就具备所有权限,不登录只具备读取数据的权限
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
],
}
1、指定使用的认证类
在全局指定默认的认证类(指定认证方式)
'DEFAULT_AUTHENTICATION_CLASSES': [
# b.Session会话认证
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
2、指定使用的权限类
在全局指定默认的权限类(当认证通过之后,可以获取何种权限)
'DEFAULT_PERMISSION_CLASSES': [
# AllowAny不管是否有认证成功,都能获取所有权限
# IsAdminUser管理员(管理员需要登录)具备所有权限
# IsAuthenticated只要登录,就具备所有权限
# IsAuthenticatedOrReadOnly,如果登录了就具备所有权限,不登录只具备读取数据的权限
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
],
- AllowAny不管是否有认证成功,都能获取所有权限
- IsAdminUser管理员(管理员需要登录)具备所有权限
- IsAuthenticated只要登录,就具备所有权限
- IsAuthenticatedOrReadOnly,如果登录了就具备所有权限,不登录只具备读取数据的权限
二、配置数据库
在settings.py 文件中,DATABASES 配置数据库信息
DATABASES = {
'default': {
# mysql数据库的引擎
'ENGINE': 'django.db.backends.mysql',
# 数据库的名称,需要连接mysql下具体某一个数据库的名称
'NAME': 'my_django',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
具体的数据库配置方式,参考:
django ORM框架(操作数据库)第一章_做测试的喵酱的博客-CSDN博客
三、初始化用户系统
1、生成迁移脚本
python manage.py makemigrations
2、执行迁移脚本
python manage.py migrate
3、创建超级管理员
python manage.py createsuperuser
设置超级管理员的账号和密码。
miaojiang
cs123456
四、可浏览api页面(登录路由配置)可忽略,不重要
1、在全局urls.py文件中设置登录路由
urlpatterns = [
# 在全局路由表中添加rest_framework.urls子路由
# a.rest_framework.urls提供了登录和登出功能(返回的是一个HTML页面,并不是接口)
path('api/', include('rest_framework.urls'))
]
2、局setting.py文件中,注释掉csrf
五、自定义Users模块(可忽略)
当Django自带用户模块,不能满足我们需要时,需要自自定义用户模块
这里我们使用自定义的user模块,需要继承系统自带的User模块。
1、创建users应用
python3 manage.py startapp users
2、注册users应用,在setting.py文件中,注册users
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users'
]
3、自定义用户模块,继承User
from django.db import models
from django.contrib.auth.models import User
class UserModel(User):
mobile = models.CharField(max_length=11)
username = models.CharField()
4、在setting文件中,设置自定义用户模块
# 指定使用的用户模型类,默认为auth子应用下的User
AUTH_USER_MODEL = 'users.UserModel'
六、JWT类型的Token介绍 (简单了解)
原文地址:
https://www.cnblogs.com/crowbrother/p/14813754.html
JWT:Json Web Token 字符串
eyJhbGciOiI6IkRFRiJ9.eNqEj0GOhCAURO_ohbw8ZqUaEUDMe6F.2A2jGp9sAw-QdkOVmm_dfD6Q
一个JWT实际上就是一个字符串,它由三部分组成:header头部、playload载荷、sign签名。
6.1 header头部
描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。表示成一个JSON对象,经base64编码形成第一部分。
例如:
{
'typ': 'JWT', //类型
'alg': 'HS256' //sign的加密算法
}
base64编码:eyJhbGciOiI6IkRFRiJ9
6.2 playload载荷
其实就是自定义的数据,一般存储用户Id,用户名、过期时间等信息。也就是JWT的核心所在,因为这些数据就是使后端知道此token是哪个用户已经登录的凭证。而且这些数据是存在token里面的,由前端携带,所以后端几乎不需要保存任何数据。
例如:
{
'uid': '1234567', //用户编号
'name': 'kobe', //用户名
'exp': '20210526121212' //过期时间
}
base64编码:eNqEj0GOhCAURO_ohbw8ZqUaEUDMe6F
6.3 sign签名
1.头部和载荷各自由base64加密后用 . 连接起来,然后就形成了xxx.yyy的前两段token。
2.最后一段token的形成:前两段字符串xxx.yyy 加入一个密钥用sha256算法或者其他算法加密形成不可逆的密文sign。
哈希算法生成的sign:2A2jGp9sAw-QdkOVmm_dfD6Q
pip install pyjwt
七、Django 使用jwt token 认证
7.1 应用jwt token认证
1、安装djangorestframework-jwt
pip install djangorestframework-jwt
2、在setting文件中,认证方式,增加jwt token认证
REST_FRAMEWORK = {
# 指定使用的认证类
# a.在全局指定默认的认证类(指定认证方式)
'DEFAULT_AUTHENTICATION_CLASSES': [
# 1)指定使用JWT TOKEN认证类
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# b.Session会话认证
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
}
3、在全局路由表中添加obtain_jwt_token路由(可以使用用户名和密码进行认证)
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('user/login/', obtain_jwt_token),
]
4、启动项目,进行登录
启动项目:
python manage.py runserver
启动项目,访问 127.0.0.1:8000/user/login,
post 请求 , 使用上面创建的超级用户miaojiang进行登录
登录成功,返回一个token信息。
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Im1pYW9qaWFuZyIsImV4cCI6MTY4NTQzNjUzNywiZW1haWwiOiIxNDIxOTE0NDY3QHFxLmNvbSJ9.mALGDOW1TFRuz81svmPljMDIbuuy3GlTDsqKJPE6PNo"
}
5、使用jwt token 做请求
将token值设置请求头参数,key为Authorization,value为JWT token值
如
注意,JWT 与token之间,有一个空格。
7.2 设置token过期时间
在setting.py中设置
import datetime
JWT_AUTH = {
# 指定TOKEN过期时间,默认为5分钟,可以使用JWT_EXPIRATION_DELTA指定
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
指定TOKEN过期时间,默认为5分钟,可以使用JWT_EXPIRATION_DELTA指定。
7.3 自定义登录返回信息
上述登录,返回信息只有一个token,我们想要将用户的一些其他信息也返回给前端。通过重写
jwt_response_payload_handler 方法实现。
1、在utils文件夹下,新建handle_jwt_response.py
def jwt_response_payload_handler(token, user=None, request=None):
return {
'user_id': user.id,
'username': user.username,
'token': token
}
将我们需要的信息,返回。
2、在setting.py文件中,指定刚刚自定义的方法
JWT_AUTH = {
# 修改处理payload的函数
'JWT_RESPONSE_PAYLOAD_HANDLER':
'utils.handle_jwt_response.jwt_response_payload_handler',
}
八、Django 使用bearer token 认证
实现功能:
修改JWT TOKEN认证请求头中Authorization value值的前缀,默认为JWT
具体方法:
在setting.py文件中,定义JWT_AUTH = {},JWT_AUTH_HEADER_PREFIX 的值为 bearer
JWT_AUTH = {
# 修改JWT TOKEN认证请求头中Authorization value值的前缀,默认为JWT
'JWT_AUTH_HEADER_PREFIX': 'bearer',
}
使用