django rest_framework 之 JWT 认证简单流程

1. 安装 djangorestframework_jwt

pip install djangorestframework-jwt

2. 基本配置

在django配置文件的 REST_FRAMEWORK 配置项(没有就自己建一个)中,配置开启jwt认证

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':(
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # jwt
         ...
    ),
    ...
}

然后再配置 jwt的认证属性

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}

*自定义jwt响应内容(默认只响应一个token)

# start_drf.utils.py
def jwt_response_payload_handler(token, user=None, request=None):
    """
       自定义jwt认证成功返回数据
       """
    return {
        'token': token,
        'id': user.id,
        'username': user.username
    }

*然后将自定义的jwt响应方法配置到配置文件中

JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'start_drf.utils.jwt_response_payload_handler',
}

配置url路径(假设认证路径为 /authoricates/)

urlpatterns = [
    # POST xxx/authorizations/
    url(r'^authorizations/$', obtain_jwt_token)
]

3. 原理分析

客户端访问时先进入url, 找到对应的视图obtain_jwt_token

# views.py
obtain_jwt_token = ObtainJSONWebToken.as_view()

class ObtainJSONWebToken(JSONWebTokenAPIView):
    serializer_class = JSONWebTokenSerializer

jwt_response_payload_handler = api_settings.JWT_RESPONSE_PAYLOAD_HANDLER

class JSONWebTokenAPIView(APIView):
	...
	    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            user = serializer.object.get('user') or request.user
            token = serializer.object.get('token')
            response_data = jwt_response_payload_handler(token, user, request)
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                expiration = (datetime.utcnow() +
                              api_settings.JWT_EXPIRATION_DELTA)
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expires=expiration,
                                    httponly=True)
            return response

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# serializer.py
class JSONWebTokenSerializer(Serializer):
	...
	    def validate(self, attrs):
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }

        if all(credentials.values()):
            user = authenticate(**credentials)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                payload = jwt_payload_handler(user)

                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)
  1. 由源码可以看到 obtain_jwt_token 相当于调用了 ObtainJSONWebToken.as_view()
  2. 登录时使用的是post方式提交,所以进入到了ObtainJSONWebToken的父类JSONWebTokenAPIView的post方法中,
  3. 然后 self.get_serializer 又使用了ObtainJSONWebToken中配置的 serializer_class: JSONWebTokenSerializer, 调用serializer.is_valid()方法,即JSONWebTokenSerializer的validate方法,
  4. 验证用户,JSONWebTokenSerializer的validate方法又使用了 django配置中的AUTHENTICATION_BACKENDS属性(自定义的话需要继承django默认的ModelBackend),来调用其类中的authenticate方法,验证用户使用允许登录。
  5. 验证成功后,调用jwt_response_payload_handler()方法,这个方法具体方法内容在JWT_RESPONSE_PAYLOAD_HANDLER配置项中(就是前面自定义的jwt响应内容配置项)

你可能感兴趣的:(python,python,rabbitmq,batch)