Pinax & Apache: deliver Attachments only to authenticated users
I want that Apache and Pinax only deliver Attachments to authenticated users.
I found this post, but i can't make it work.
My Apache-conf-file:
WSGIPythonPath /usr/local/bin/python
<VirtualHost *:80&开发者_运维百科gt;
ServerName www.domain.com
ServerAlias domain.com
WSGIDaemonProcess k-production python-path=/path/to/app/pinax-env/lib/python2.6/site-packages
WSGIProcessGroup k-production
Alias /site_media /path/to/app/cp/site_media
<Directory /path/to/app/cp/site_media>
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias /site_media/media/attachments /path/to/app/cp/deploy/pinax.wsgi
<Directory /path/to/app/cp/site_media/media/attachments>
Deny from all
</Directory>
XSendFile On
XSendFileAllowAbove On
WSGIScriptAlias / /path/to/app/cp/deploy/pinax.wsgi
<Directory /path/to/app/cp/deploy>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
and my (still rough) view, that should get called:
@login_required
def sendfile(request, slug):
app, content_object_id, img = slug.split('/')
project_file = get_object_or_404(Attachment, attachment_file = 'attachments/'+slug)
response = HttpResponse()
response['X-Sendfile'] = os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug)
content_type = 'application/octet-stream'
response['Content-Type'] = content_type
response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug))
return response
Apache throws a 403 no matter if the user is logged in.
Via the develoment-server i can access the view, but no data will get transmitted.
What is wrong?
I was trying to do pretty much exactly the same thing, and the solution turned out to be not using WSGIScriptAlias, and instead using a regular Alias to a directory that defined a wsgi handler. For the view I basically just wrote a wrapper around django.views.static.serve.
My apache conf ended up looking like this:
# myproject
<VirtualHost *:8080>
#DocumentRoot /var/www/myproject/public
ServerName myproject
ErrorLog /var/www/myproject/logs/apache_error_log
CustomLog /var/www/myproject/logs/apache_access_log common
AliasMatch ^/(media/uploads/protected/.*) /var/www/myproject/src/myproject-trunk/server/django.wsgi/$1
Alias /media/ /var/www/myproject/public/media/
Alias / /var/www/myproject/src/myproject-trunk/server/django.wsgi/
<Directory /var/www/myproject/src/myproject-trunk/server>
Options ExecCGI
AddHandler wsgi-script .wsgi
# WSGIApplicationGroup %{GLOBAL}
Order allow,deny
Allow from all
</Directory>
<Directory /var/www/myproject/public/media>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
Try to concentrate on the development server first - since it is a simpler setup and thus less error prone.
Perhaps try this:
@login_required def sendfile(request, slug):
## these are never used
# app, content_object_id, img = slug.split('/')
# project_file = get_object_or_404(Attachment, attachment_file = 'attachments/'+slug)
response = HttpResponse()
response['X-Sendfile'] = os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug)
import pdb; pdb.set_trace()
# your development server will stop here
# you can now inspect the your context, e.g.
# >> p response['X-Sendfile']
# this should print the value of response['X-Sendfile']
# >> c
# this will continue program execution
# for more commands see http://www.python.org/doc/2.4/lib/debugger-commands.html
content_type = 'application/octet-stream'
response['Content-Type'] = content_type
# Content-Disposition filename is only for suggesting a name for the file
# when the user tries to download it, e.g.:
# response['Content-Disposition'] = 'attachment; filename='localfile.txt'
response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug))
return response
But by using the dev server you won't get any files served, since Apache will do the file serving. You can just ensure, the data sent to apache is correct. Or use (not recommended for your production server)
f = open(os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug), 'rb')
response = HttpResponse(f.read())
instead of
response = HttpResponse()
response['X-Sendfile'] = os.path.join(settings.MEDIA_ROOT, 'attachments/'+slug)
Some Links:
- Similar topic at stackoverflow
精彩评论