用户登录功能
一、创建用户子应用
进入虚拟环境,新建一个名为‘users’的子应用,并在settings.py中注册。
二、重写子应用的模型类
Django为我们提供了用户模块,我们可以直接使用,但是如果有需要新增的字段,我们可以继承Django中提供的,并在此基础上新增修改。
from django.contrib.auth.models import AbstractUser
class Users(AbstractUser):
mobile = models.CharField(max_length=11)
自己定义后还需要在全局配置文件中指定一下。AUTH_USER_MODEL的值为子应用名.model类名。
AUTH_USER_MODEL = 'users.Users'
当前我们Django提供的模型够用,暂时不需要做以上的重写。
三、认证和授权?
- 认证:使用哪种方式能获取权限
- 授权:通过认证之后,能具备哪些权限
3.1 实现认证和授权
在Django中,只要继承了APIView就有了认证和授权的功能。
3.2 修改认证方式
3.2.1 全局修改(常用)
阅读源码,看到Django提供了Session认证。我们可以重写DEFAULT_AUTHENTICATION_CLASSES来修改认证方式。
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': [
# 这是源码内容
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
}
3.2.2 类视图中修改(不常用)
上面是在全局指定认证类,当然我们也可以在类视图中指定。(一般不在类视图中指定)
from rest_framework import authentication
class ProjectViewSet(viewsets.ModelViewSet):
authentication_classes = [authentication.SessionAuthentication, authentication.BasicAuthentication]
3.3 修改权限类
Django默认DRF框架使用的权限类为AllowAny,具备所有权限,我们也可以修改权限。
DRF中的权限:
- AllowAny
- IsAuthenticated
- IsAdminUser
- IsAuthenticatedOrReadOnly
3.3.1 全局修改(不常用)
在全局修改权限(一般不这样修改)
REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
# 指定DRF中提供的IsAuthenticated权限类,只要登录就具备所有权限,如果不登录,则部具备任何权限
# 'rest_framework.permissions.IsAuthenticated',
],
}
3.3.2 类视图中修改(常用)
一般来说我们会在类视图中指定权限,类视图中权限的优先级最高。需要设置权限的指定,不需要权限就不用指定。
from rest_framework import permissions
class ProjectViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticated]
这样,就需要具备权限才能请求接口。
四、新增登录路由
但是我们没有登录的入口,我们可以在全局路由中指定drf提供的登录路由。
urlpatterns = [
...
path('api/', include('rest_framework.urls')),
]
此时,访问http://127.0.0.1:8000/api/login/
就可以进行登录了。
五、新建超级用户
但是我们没有用户,我们可以通过命令行来新建超级用户。
进入虚拟环境,输入python manage.py createsuperuser
,根据提示依次输入用户名、邮件地址、密码即可。
此时我们数据库的auth_user表中就多了一条用户数据。
六、jwt
我们项目中使用jwt来做用户认证。
6.1 安装djangorestframework-jwt
在虚拟环境中使用命令pip install -i https://pypi.douban.com/simple djangorestframework-jwt
安装jwt。
6.2 配置jwt
在settings.py文件中进行kwt配置
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': [
# 指定使用JWT Token认证
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 指定session会话认证类
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
],
}
6.3 添加路由
在users子应用中添加urls.py文件。
obtain_jwt_token是django提供的路由
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token)
]
在全局路由中添加路由指向子路由。
urlpatterns = [
...
path('users/', include('users.urls')),
]
此时我们通过api文档请求这个接口,就能够返回token了。
6.4 修改jwt配置
6.4.1 接口测试时token的使用
当使用postman进行接口测试后,我们想要获得权限,需要在headers增加value为Authorization
,值为JWT token值
,就拥有权限了。
这里的value前缀为JWT,我们可以在全局配置文件中修改前缀的值。
JWT_AUTH = {
# 前端需要在请求头中传递key为Authorization,Bears为前缀 token值
'JWT_AUTH_HEADER_PREFIX': 'Bears',
}
此时,我们的value就需要输入Bears token值
。(此处我们暂时不做修改)
6.4.2 修改用户登录过期时间
在全局配置文件settings.py中修改。
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=2),
}
七、修改接口默认返回值
但是当前只返回了token,实际上我们还需要username和userid,我们需要把这两个字段也一并返回。
追踪源码发现,返回值都有什么,是jwt_response_payload_handler方法决定的,我们可以重写这个方法。在utils文件夹中新增一个文件handle_jwt_response.py。
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user_id': user.id,
'username': user.username
}
这是django并不认识我们写的这个方法,我们需要在全局配置文件中重新指定payload_handler为我们自己写的方法。值为我们自己写的方法的引用。
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER':
'utils.handle_jwt_response.jwt_response_payload_handler',
}
这样django就会执行我们自己写的这个方法。我们就返回了需要的值。完美!