Flask - Learning Notes - Registration

This article mainly introduces Python's Flask framework and Nginx's static file access restriction function. Nginx uses its own XSendfile, which can be consulted by friends who need it.

Nginx configuration

Ngnix, a high-performance web server, is undoubtedly the current darling. Excellent performance, flexible and scalable, in the field of servers to fight the world.

Static files are an integral part of most website s. Nginx is also a common way to process static files. However, some static files are not exposed to any user under any circumstances. For example, some files for users to download, some users upload pictures related to user privacy, and so on. We want users to be accessible when they are logged in, but users who are not logged in are not visible.

Rough processing, in the back-end program can be filtered, rendering the page, in the view logic to verify user login, and then return to the corresponding page. For example, the following flask code (pseudocode)

@app.router('/user/idcard'):
def user_idcard_page():
 if user is login:
  return '<img src="http://files.jb51.net/upload/user/xxx.png'>"
 else:
  reutrn '<p>Pemission Denied<p>', 403

However, there is another problem with this kind of processing. Static files are handed over to nginx for processing. If hacker finds the absolute address of the files, he can access them directly. http://www.example.com/upload/user/xxx.png It's also possible. It happens that these files also involve user privacy, such as the ID photos uploaded by users. Then the farmer does not want to be reported in the media the next day that there is a loophole in the well-known website XXX and Hacker has access to information such as user ID cards.

To do this, you can use a small function of Nginx - XSendfile. The principle is relatively simple, probably using request redirection.

We know that if Nginx is used as the reverse proxy of the front end of the server, a request comes in, nginx catches it first, and then forwards it to the back end according to the rules, or directly processes the return. The former deals with some dynamic logic while the latter deals with static files. So in the example above, Nginx returns directly by accessing the absolute address of the static file without calling the user_idcard_page of the back end as a logical restriction.

To solve this problem, the XSendfile function provided by nginx, in short, uses internal instructions. This instruction indicates that only internal requests are accepted, that is, requests forwarded from the back end. In the view logic of the back end, the headers information X-Accel-Redirect needs to be written explicitly.

The pseudocode is as follows:

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

After such processing, static resources can be redirected. Such usage is still relatively common, many download servers can do download processing according to the user's rights through such means.

Flask

Flask is my favorite web framework. Flask even implements a sendfile method, which is simpler than the above method. I made a virtual machine with vagrant and implemented the above requirement with Flask. The specific code is as follows:

Project structure

project struct

project
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 files
  location /static/(.*) {
    root /vagrant/;

  }
  # Files uploaded by users need to be restricted
  location /upload/(.*) {
    alias /vagrant/;
    internal;    # Instructions to accept only internal requests
  }
}

Flask code

This is the normal single file flask framework app.py, which implements registration permissions to access.

from functools import wraps
from flask import Flask, render_template, redirect, url_for, session, send_file

app = 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_required
def user():

 return render_template('upload.html')

# File View Processing Uploaded by the User, where the request is returned to nginx
@app.route('/upload/<filename>')
@login_required
def 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)

---------–

The blueprint I used is views.py below. It should be noted that the password of the blueprint should be registered in the running file.

from flask import render_template
from user import user
from flask import Flask, render_template, redirect, url_for, session, send_file
from functools import wraps



def login_required(f):
 @wraps(f)
 def decorated_function(*args, **kwargs):
  if not session.get('login'):
   return redirect(url_for('login'))
  return f(*args, **kwargs)
 return decorated_function


@user.route('/')
@user.route('/blog')
@login_required   #This modifier represents access only when registered.
def blog():
    return render_template('user/blog.html')


@user.route('/login')
def login():
 session['login'] = True
 return 'log in'

@user.route('/logout')
def logout():
 session['login'] = False
 return 'log out'

Blueprint Registration Password

#encoding: utf-8

from flask import Flask
from asset import asset
from user import user
from main import main
from study import study




app = Flask(__name__,
              template_folder='templates',  # Specify template paths, either relative or absolute.
              static_folder='static',  # Specify static file prefix, default static file path with prefix
              # static_url_path='/opt/auras/static',     #Specify a static file storage path.
              )
app.register_blueprint(asset, url_prefix='/asset')  # Register the asset blueprint and specify the prefix.
app.register_blueprint(user, url_prefix='/user')  # Register the user blueprint and specify the prefix.
app.register_blueprint(study, url_prefix='/study')  # Register the study blueprint and specify the prefix.
app.register_blueprint(main,)  # Register main blueprint with no prefix specified.


app.config['SECRET_KEY'] = 'you never guess'#Passwords required to register permissions, otherwise errors will be reported

if __name__ == '__main__':
    app.run()

Keywords: Nginx Session Python Web Server

Added by karldesign on Sat, 13 Jul 2019 22:51:54 +0300