八、DRF自带用户模块
DRF自带用户模块接口
path('api/', include('rest_framework.urls'))
创建登陆的路径
数据库迁移后可以访问
在pycharm中选择Tools-Run manage.py文件, 输入createsuperuser进行创建用户
在用户模块的url中导入from rest_framework_jwt.views import obtain_jwt_token视图
再将路径path('login/', obtain_jwt_token)添加到urlpatterns中
权限设置
可以在需要权限设置模块的view视图文件中添加, 或者直接在全局setting中REST_FRAMEWORK配置, 对全局有效
#只有登陆才可以访问 permission_classes = [permissions.IsAuthenticated] #不登录也可以访问,这是默认的 permission_classes = [permissions.AllowAny] #只有管理员才可以访问 permission_classes = [permissions.IsAdmin] #如果登陆了就都可以访问,不登陆只能获取数据,不能修改数据 permission_classes = [permissions.IsAuthenticatedOrReadOnly]
添加Session和Token认证
在全局setting中REST_FRAMEWORK中配置
安装jwt模块:pip install -i https://pypi.douban.com/simple djangorestframework-jwt
开启跨域需要安装:pip install -i https://pypi.douban.com/simple django-cors-headers
# 指定认证类(指定的是认证的方式) 'DEFAULT_AUTHENTICATION_CLASSES': [ # token认证 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # DRF框架默认情况下,使用的是用户会话认证(session) 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ]
Token认证更改前缀
原本为JWT开头, 更改成Bearer, 单独在setting中添加
JWT_AUTH = { # 默认token的过期时间是五分钟,这里设置的是一天 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # 修改token的前缀,原来是JWT,修改为Bearer 'JWT_AUTH_HEADER_PREFIX': 'Bearer', # 对token返回的数据进行重写 'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler' }
Session认证和Token认证的区别
Session认证的过程:
当用户登陆成功后用户会话信息会保存在后端数据库, 存有SessionId, 过期时间等, 返回的响应头中会有set-cookie字段保存SessionId, 当浏览器接收到响应头中有set-cookie, 就会把里面的SessionId取出来放在浏览器的cookie里面, 那么浏览器发送请求时会携带这个SessionId, 后端接收到后会去数据库校验SessionId及是否过期
Session的特点:
数据保存在服务端,会增加服务器开销
分布式架构中,难以维持Session会话同步
有CSRF攻击风险
Token认证过程:
当用户登陆成功后,会创建加密的Token令牌, 会把Token放在响应数据中返回给前端, 前端会存放在会话存储或本地存储中,会话存储浏览器关掉以后就清空了,本地存储浏览器关掉后还是存在的
Token特点:
保存在客户端
跨语言, 跨平台(window,linux都适用)
拓展性强
鉴权性能高
Token的组成
由三部分组成:
头部(header)
声明类型
声明加密算法,默认为HS256
头部采用base64加密,可以轻松解密,没有安全性
载荷(payload)
存放过期时间,签发用户等
可以添加用户的非敏感信息
采用base64加密,可以轻松解密,没有安全性
签证(signaturn)
使用base64加密之后的header+.+使用base64加密之后的payload+使用HS256算法加密,同时使用secret加盐处理
增加Token的返回信息
目前框架自带的Token返回只有一个Token值,那么假如有一个需求,需要返回Token的同时,返回用户的用户名和id,实现方法如下:
首先查看源码,我们可以看到有一个jwt_response_payload_handler方法,token就是它返回的,那么就可以重写它(因为不止针对一个模块,所以可以把这个方法写在公共模块内),重写后如下:
def jwt_response_payload_handler(token, user=None, request=None): return { "token": token, 'user_id': user.id, 'user_name': user.username }
然后再把重写后的方法写在setting的JWT_AUTH中
'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler'
实现注册模块
class RegisterView(CreateAPIView): """ 注册接口,因为CreateAPIView继承了GenericAPIView,所以需要指定序列化器类和queryset查询集 但我们注册只是创建,并没做查询,所以可以不用指定queryset """ serializer_class = serializers.RegisterSerializer
因为CreateAPIView中继承了CreateModelMixin,里面有调用了serializer.save()方法,那么会调用create方法,所以需要在serializer中实现
def create(self, validated_data): #因为在数据库中无需保存确认密码,所以删除确认密码字段 validated_data.pop('password_confirm') # User模块可以使用create_user方法来创建用户, 会对密码进行加密 user = User.objects.create_user(**validated_data) # 生成token返回 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) user.token = token return user
浙公网安备 33010602011771号