如何通过保护仅经过身份验证的用户可以看到的URL来使文件成为私有文件

时间:2021-04-09 13:28:59

I was wondering if there is a way to secure an image or a file to be hidden when it is not authenticated.

我想知道是否有一种方法可以保护图像或文件在未经过身份验证时被隐藏。

Suppose there is an image in my website which can only be seen if that user is authenticated. But the thing is I can copy the url or open the image in the new tab.

假设我的网站中有一个图像,只有在该用户通过身份验证时才能看到。但问题是我可以复制网址或在新标签中打开图片。

http://siteis.com/media/uploaded_files/1421499811_82_Chrysanthemum.jpg

http://siteis.com/media/uploaded_files/1421499811_82_Chrysanthemum.jpg

And again, even if I am not authenticated, I can view that particular image by going to that url. So, my my problem is, how do I secure the files, so that only authenticated users will see?

而且,即使我没有通过身份验证,我也可以通过访问该网址来查看该特定图像。所以,我的问题是,如何保护文件,以便只有经过身份验证的用户才会看到?

Update:

更新:

view:

视图:

def pictures(request, user_id):
    user = User.objects.get(id=user_id)
    all = user.photo_set.all()
    return render(request, 'pictures.html',{
        'pictures': all
    })

models:

楷模:

def get_upload_file_name(instance, filename):
    return "uploaded_files/%s_%s" %(str(time()).replace('.','_'), filename)

class Photo(models.Model):
    photo_privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
    user = models.ForeignKey(User)
    image = models.ImageField(upload_to=get_upload_file_name)

settings:

设置:

if DEBUG:
    MEDIA_URL = '/media/'
    STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "myproject", "static", "static-only")
    MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "myproject", "static", "media")
    STATICFILES_DIRS = (
    os.path.join(os.path.dirname(BASE_DIR), "myproject", "static", "static"),
    )

Update:

更新:

template:

模板:

{% if pictures %}
    {% for photo in pictures %}
        <img src="/media/{{ photo.image }}" width="300" alt="{{ photo.caption }}"/>
    {% endfor %}
{% else %}
    <p>You have no picture</p>
{% endif %}

url:

网址:

url(r'^(?P<user_name>[\w@%.]+)/photos/$', 'pictures.views.photos', name='photos'),

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

3 个解决方案

#1


7  

By securing any media file not to serve by anonymous user, better way url protection.

通过保护任何媒体文件不被匿名用户提供,更好的方式保护网址。

Code ( Updated ):

代码(更新):

from django.conf.urls import patterns, include, url
from django.contrib.auth.decorators import login_required
from django.views.static import serve
from django.conf import settings

from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import HttpResponse

@login_required
def protected_serve(request, path, document_root=None):
    try:
        obj = Photobox.objects.get(user=request.user.id)
        obj_image_url = obj.image.url
        correct_image_url = obj_image_url.replace("/media/", "")
        if correct_image_url == path:
            return serve(request, path, document_root)
    except ObjectDoesNotExist:
        return HttpResponse("Sorry you don't have permission to access this file")


url(r'^{}(?P<path>.*)$'.format(settings.MEDIA_URL[1:]), protected_serve, {'file_root': settings.MEDIA_ROOT}),

Note: previously any logged in user can access any page, now this update restrict non user to view other files...

注意:以前任何登录用户都可以访问任何页面,现在此更新限制非用户查看其他文件...

#2


1  

The easiest option is to serve the file from django, and then add the @login_required decorator to the view, like this:

最简单的选择是从django提供文件,然后将@login_required装饰器添加到视图中,如下所示:

import os
import mimetypes
from django.core.servers.basehttp import FileWrapper
from django.contrib.auth.decorators import login_required

@login_required
def sekret_view(request, path=None):
   filename = os.path.basename(path)
   response = HttpResponse(FileWrapper(open(path)),
                           content_type=mimetypes.guess_type(path)[0])
   response['Content-Length'] = os.path.getsize(path)
   return response

#3


1  

It would be better to handle just the authentication, and let your webserver handle the serving of files. It's probably good to put them in a different directory than your settings.MEDIA_ROOT, to prevent your webserver from serving the files before you handle the request, e.g. project_root/web-private/media/.

最好只处理身份验证,让您的网络服务器处理文件服务。将它们放在与settings.MEDIA_ROOT不同的目录中可能是好的,以防止您的网络服务器在处理请求之前提供文件,例如: project_root / WEB-私人/媒体/。

import os

@login_required
def protected_file(request, path):
    # set PRIVATE_MEDIA_ROOT to the root folder of your private media files
    name = os.path.join(settings.PRIVATE_MEDIA_ROOT, path)
    if not os.path.isfile(name):
        raise Http404("File not found.")

    # set PRIVATE_MEDIA_USE_XSENDFILE in your deployment-specific settings file
    # should be false for development, true when your webserver supports xsendfile
    if settings.PRIVATE_MEDIA_USE_XSENDFILE:
        response = HttpResponse()
        response['X-Accel-Redirect'] = filename # Nginx
        response['X-Sendfile'] = filename # Apache 2 with mod-xsendfile
        del response['Content-Type'] # let webserver regenerate this
        return response
    else:
        # fallback method
        from django.views.static import serve
        return serve(request, path, settings.PRIVATE_MEDIA_ROOT)

As your webserver is way better at serving static files than Django, this will speed up your website. Check django.views.static.serve for an idea how to sanitize file names etc.

由于您的网络服务器在提供静态文件方面比Django更好,这将加快您的网站速度。检查django.views.static.serve,了解如何清理文件名等。

#1


7  

By securing any media file not to serve by anonymous user, better way url protection.

通过保护任何媒体文件不被匿名用户提供,更好的方式保护网址。

Code ( Updated ):

代码(更新):

from django.conf.urls import patterns, include, url
from django.contrib.auth.decorators import login_required
from django.views.static import serve
from django.conf import settings

from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import HttpResponse

@login_required
def protected_serve(request, path, document_root=None):
    try:
        obj = Photobox.objects.get(user=request.user.id)
        obj_image_url = obj.image.url
        correct_image_url = obj_image_url.replace("/media/", "")
        if correct_image_url == path:
            return serve(request, path, document_root)
    except ObjectDoesNotExist:
        return HttpResponse("Sorry you don't have permission to access this file")


url(r'^{}(?P<path>.*)$'.format(settings.MEDIA_URL[1:]), protected_serve, {'file_root': settings.MEDIA_ROOT}),

Note: previously any logged in user can access any page, now this update restrict non user to view other files...

注意:以前任何登录用户都可以访问任何页面,现在此更新限制非用户查看其他文件...

#2


1  

The easiest option is to serve the file from django, and then add the @login_required decorator to the view, like this:

最简单的选择是从django提供文件,然后将@login_required装饰器添加到视图中,如下所示:

import os
import mimetypes
from django.core.servers.basehttp import FileWrapper
from django.contrib.auth.decorators import login_required

@login_required
def sekret_view(request, path=None):
   filename = os.path.basename(path)
   response = HttpResponse(FileWrapper(open(path)),
                           content_type=mimetypes.guess_type(path)[0])
   response['Content-Length'] = os.path.getsize(path)
   return response

#3


1  

It would be better to handle just the authentication, and let your webserver handle the serving of files. It's probably good to put them in a different directory than your settings.MEDIA_ROOT, to prevent your webserver from serving the files before you handle the request, e.g. project_root/web-private/media/.

最好只处理身份验证,让您的网络服务器处理文件服务。将它们放在与settings.MEDIA_ROOT不同的目录中可能是好的,以防止您的网络服务器在处理请求之前提供文件,例如: project_root / WEB-私人/媒体/。

import os

@login_required
def protected_file(request, path):
    # set PRIVATE_MEDIA_ROOT to the root folder of your private media files
    name = os.path.join(settings.PRIVATE_MEDIA_ROOT, path)
    if not os.path.isfile(name):
        raise Http404("File not found.")

    # set PRIVATE_MEDIA_USE_XSENDFILE in your deployment-specific settings file
    # should be false for development, true when your webserver supports xsendfile
    if settings.PRIVATE_MEDIA_USE_XSENDFILE:
        response = HttpResponse()
        response['X-Accel-Redirect'] = filename # Nginx
        response['X-Sendfile'] = filename # Apache 2 with mod-xsendfile
        del response['Content-Type'] # let webserver regenerate this
        return response
    else:
        # fallback method
        from django.views.static import serve
        return serve(request, path, settings.PRIVATE_MEDIA_ROOT)

As your webserver is way better at serving static files than Django, this will speed up your website. Check django.views.static.serve for an idea how to sanitize file names etc.

由于您的网络服务器在提供静态文件方面比Django更好,这将加快您的网站速度。检查django.views.static.serve,了解如何清理文件名等。