Using Django Rest Framework as security layer for

2019-05-07 07:09发布

问题:

I'm trying to protect my remote server file system from unauthorized users. I have a remote storage on a different server that store and process PDF's and PNG's from all kind of processes.

I'm using Python 2.7 with Django 1.8 and Django Rest Framework.

I trying to implement very basic, "Proxy Layer" that will give my control on who ever use file system.

This is my view.py:

from django.conf import settings

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions

import requests

class Reports(APIView):
    permission_classes = (permissions.AllowAny,)  #Thats only for now...

    def get(self, request, ssn, validity, file):
        response = requests.get(settings.PROXY_BASE_URL + "/reports/" + ssn + "/" + validity + "/" + file)
        return Response(response)

This concept works for any other GET POST PUT DELETE request that is text based response (For example json response from the remote server).

My problem is when I call this view, I get in the browser the default REST method definition page.

This is the response screenshot

回答1:

As @AlexMorozov said in his comment, you should revert back to HttpResponse. You can see by exploring this Django Snippet.

Here is the code as I see it:

from django.conf import settings

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions

from django.http import HttpResponse

import requests
import mimetypes


class Reports(APIView):
    permission_classes = (permissions.AllowAny,)

    def get(self, request, ssn, validity, file):
        response = requests.get(settings.PROXY_BASE_URL + "/reports/" + ssn + "/" + validity + "/" + file)
        mimetype = mimetypes.guess_type(settings.PROXY_BASE_URL + "/reports/" + ssn + "/" + validity + "/" + file) #Return an array
        return HttpResponse(response, content_type=mimetype[0])

Give it a go. Good luck :)



回答2:

The problem is you can't simply wrap a requests response with a DRF Response and get it done. Change your code to:

from django.core.servers.basehttp import FileWrapper

upstream_response = requests.get(settings.PROXY_BASE_URL + "/reports/" + ssn + "/" + validity + "/" + file)
response = Response(FileWrapper(upstream_response.content), content_type='YOUR_MIME_TYPE')
response['Content-Disposition'] = 'attachment; filename="%s"' % 'your_filename.ext'
return response

BTW, there are other (more clean, IMO) ways to solve this particular task. Take a look at django-sendfile app. It offloads the actual file serving to a nginx or the server of your choice, while allowing you to check permissions and stuff.