2015-01-18 11 views
9

Ich frage mich, ob es eine Möglichkeit gibt, ein Bild oder eine Datei zu sichern, die versteckt werden soll, wenn sie nicht authentifiziert wird.Wie man eine Datei privat macht, indem man die URL sichert, die nur authentifizierte Benutzer sehen können

Angenommen, es gibt ein Bild auf meiner Website, das nur angezeigt wird, wenn dieser Benutzer authentifiziert ist. Aber die Sache ist, ich kann die URL kopieren oder das Bild in der neuen Registerkarte öffnen.

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

Und wieder, auch wenn ich nicht authentifiziert bin, kann ich dieses bestimmte Bild anzeigen, indem Sie zu dieser URL gehen. Also, mein Problem ist, wie sichere ich die Dateien, so dass nur authentifizierte Benutzer sehen können?

Update:

Ansicht:

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

Modelle:

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) 

Einstellungen:

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:

Vorlage:

{% 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>[\[email protected]%.]+)/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) 
+1

Ein Weg wäre, einen Controller die URL '/ media/uploaded_files/*' zu behandeln und nach Anmeldeinformationen zu überprüfen. Wenn nicht autorisiert, geben Sie einen 404-Status zurück. – Javier

+0

@Javier Könnten Sie sich bitte das Update ansehen und mir sagen, wie es geht? Vielen Dank. – Robin

+0

Die URL für die Dateien sollte jetzt eine logische URL sein, nicht Teil von statisch. Und dann würde ich etwas tun, was dem @Burhan Khalid ähnlich war. – Javier

Antwort

7

Durch Sicherung aller Mediendateien nicht von Anony dienen mous Benutzer, bessere Weise URL-Schutz.

-Code (aktualisiert):

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}), 

Hinweis: vorher alle angemeldeten Benutzer jede Seite zugreifen können, jetzt dieses Update nicht Benutzer beschränken andere Dateien anzuzeigen ...

+0

Könnten Sie mir bitte auch zeigen, wie ich die Fotos in der Vorlage zeige? Ich werde es wirklich zu schätzen wissen. Vielen Dank. – Robin

+1

Ja, ich habe einen Arbeitscode. Und es zeigt mir das Foto in der Vorlage. Die Sache ist, ich kann die URL des Bildes kopieren und es als anonymer Benutzer öffnen. Ich habe Ihren Code ausprobiert, Ihre Ansichten und Ihre URL kopiert. Aber nichts hat sich geändert. Würde es schätzen, wenn Sie mehr ausarbeiten könnten. – Robin

+0

Großartig! Jetzt geht es! Vielen Dank! – Robin

1

Die einfachste Möglichkeit besteht darin, die Datei von django zu dienen, und dann die @login_required decorator zu der Ansicht hinzufügen, wie folgt aus:

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 
+0

Vielen Dank für die Antwort. Aber ich bin ziemlich neu zu Django nicht so viel, wie man es in der Vorlage zeigt. Vielleicht könntest du dir bitte das Update ansehen und mir sagen wie, ich werde dir sehr dankbar sein. – Robin

1

Es wäre besser nur die Authentifizierung zu behandeln, und lassen Sie Ihren Webserver die Bereitstellung von Dateien behandeln. Es ist wahrscheinlich gut, sie in ein anderes Verzeichnis als Ihr settings.MEDIA_ROOT zu legen, um zu verhindern, dass Ihr Webserver die Dateien vor der Verarbeitung der Anfrage, z. project_root/web-private/media/.

Da Ihr Webserver statische Dateien wesentlich besser unterstützt als Django, beschleunigt dies Ihre Website. Überprüfen Sie django.views.static.serve für eine Idee, wie Sie Dateinamen usw. bereinigen.

+0

Um diese Methode zu verwenden, muss ich irgendetwas an der Apache 2-Konfiguration ändern? –

+1

@RenelChesak Ich benutze das meistens mit Ngnix. Möglicherweise müssen Sie mod_xsendfile auf Apache installieren und aktivieren, aber ich bin mir nicht sicher über die Details. – knbk

+0

Dies ist ein sehr hilfreiches Tutorial zur Einrichtung von Apache: https://www.h3xed.com/web-development/how-to-install-xsendfile-mod-xsendfile-apache-vps-web-host. @knbk Wie für Ihren Code oben, muss dies im urls.py des Hauptprojekts sein, oder muss es eine funktionsbasierte Ansicht in der Datei views.py sein? –

Verwandte Themen