八、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

 


posted @ 2020-10-22 20:35  SoleMemory  阅读(262)  评论(0)    收藏  举报