Python Flask framework and Nginx implement static file access restrictions

Source: Internet
Author: User
This article mainly introduces the Python Flask framework and Nginx's static file access restriction function. Nginx uses its own XSendfile. For more information, see Nginx configuration

Ngnix, a high-performance web server, is undoubtedly the current darling. Superior performance, flexible scalability, attacking the city and fighting the world in the server field.

Static files are an indispensable part of most websites. It is also common to use Nginx to process static files. However, some static files are not disclosed to any user in any situation. For example, some files provided for users to download and some images uploaded by users that involve user privacy. We want users to be accessible when they log on. users not logged on are invisible.

Rough processing: the backend program can perform filtering and verify the user logon in the view logic when rendering the page, and then return the corresponding page. For example, the following flask code (pseudo code)

@app.router('/user/idcard'):def user_idcard_page(): if user is login:  return '" else:  reutrn '

Pemission Denied

', 403

However, there is another problem in this process. static files are handed over to nginx for processing. If hacker finds the absolute address of the file, access http://www.example.com/upload/user/xxx.pngdirectly. These files involve user privacy, such as user-uploaded ID card photos. In this case, coders do not want to report the second day that the well-known website XXX has a vulnerability and Hacker has obtained user ID card and other information.

To make such restrictions, you can use a small feature of Nginx-XSendfile. The principle is also relatively simple, probably because request redirection is used.

We know that if Nginx is used as the reverse proxy of the front-end server and a request comes in, nginx first catches up, then forwards the request to the backend program based on the rules, or directly processes the response. The former processes some dynamic logic, while the latter processes mostly static files. Therefore, in the above example, Nginx directly returns the absolute address for directly accessing the static file without calling the backend user_idcard_page for logical restrictions.

To solve this problem, the XSendfile function provided by nginx simply uses the internal command. This command only accepts internal requests, that is, requests forwarded by the backend. In the backend view logic, you must explicitly write the headers information X-Accel-Redirect.

The pseudocode is as follows:

location /upload/(.*) {  alias /vagrant/;  internal;}@app.router('upload/
 
  ')@login_requireddef upload_file(filename): response = make_response() response['Content-Type'] = 'application/png' response['X-Accel-Redirect'] = '/vagrant/upload/%s' % filename return response
 

After such processing, you can redirect static resources. This is a common practice. many download servers can use this method to download user permissions.

Flask

Flask is my favorite web framework. Flask even implements a sendfile method, which is simpler than the above method. I used vagrant as a virtual machine and Flask to implement the above requirements. the specific code is as follows:

Project structure

project structproject app.py templates static 0.jpeg upload 0.jpeg

Nginx configuration nginx conf

Web. conf

Server {listen 80 default_server; # server_name localhost; server_name 192.168.33.10; location/{proxy_pass http: // 127.0.0.1: 8888; proxy_redirect off; proxy_set_header Host $ host: 8888; proxy_set_header X-Real-IP $ remote_addr; proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;} # normal static file location/static /(. *) {root/vagrant/;} # specify the permission to restrict the location/upload /(. *) {alias/vagrant/; internal; # only receive internal request instructions }}

Flask code

App. py

From functools import wrapsfrom flask import Flask, render_template, redirect, url_for, session, send_fileapp = Flask (_ name _) app. config ['secret _ key'] = 'You never guess 'def login_required (f): @ wraps (f) def decorated_function (* args, ** kwargs): if not session. get ('login'): return redirect (url_for ('login', next = request. url) return f (* args, ** kwargs) return decorated_function@app.route ('/') def index (): return 'index' @ app. route ('/user') @ login_requireddef user (): return render_template('upload.html') # process the file view uploaded by the user, where the request is returned to the nginx@app.route ('/upload/
 
  
') @ Login_requireddef upload (filename): return send_file ('upload /{}'. format (filename) @ app. route ('/login') def login (): session ['login'] = True return 'log in' @ app. route ('/logout') def logout (): session ['login'] = False return 'Log out' if _ name _ = '_ main _': app. run (debug = True)
 

Simple Deployment

gunicorn -w4 -b0.0.0.0:8888 app:app --access-logfile access.log --error-logfile error.log

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.