Python的Flask框架及Nginx实现静态文件访问限制功能

作者:人世间 时间:2023-08-13 03:13:38 

Nginx配置

Ngnix,一个高性能的web服务器,毫无疑问它是当下的宠儿。卓越的性能,灵活可扩展,在服务器领域里攻城拔寨,征战天下。

静态文件对于大多数website是不可或缺的一部分。使用Nginx来处理静态文件也是常见的方式。然而,一些静态文件,我们并不像任何情况下都公开给任何用户。例如一些提供给用户下载的文件,一些用户上传的涉及用户隐私的图片等。我们我希望用户登录的情况下可以访问,未登录的用户则不可见。

粗略的处理,在后端程序可以做过滤,渲染页面的时候,在视图逻辑里面验证用户登录,然后返回对应的页面。例如下面的flask代码(伪代码)


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

可是这样的处理,还有一个问题,静态文件是交给 nginx 处理的,如果hacker找到了文件的绝对地址,直接访问 http://www.example.com/upload/user/xxx.png也是可以的。恰巧这些文件又涉及用户隐私,比如用户上传的身份证照片。那么码农可不希望第二天媒体报道,知名网站XXX存在漏洞,Hacker获取了用户身份证等信息。

为了做这样的限制,可以借助 Nginx 的一个小功能----XSendfile。 其原理也比较简单,大概就是使用了请求重定向。

我们知道,如果用Nginx做服务器前端的反向代理,一个请求进来,nginx先补捉到,然后再根据规则转发给后端的程序处理,或者直接处理返回。前者处理一些动态逻辑,后者多是处理静态文件。因此上面那个例子中,直接访问静态文件的绝对地址,Nginx就直接返回了,并没有调用后端的 user_idcard_page做逻辑限制。

为了解决这个问题,nginx提供的 XSendfile功能,简而言之就是用 internal 指令。该指令表示只接受内部的请求,即后端转发过来的请求。后端的视图逻辑中,需要明确的写入X-Accel-Redirect这个headers信息。

伪代码如下:


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

经过这样的处理,就能将静态资源进行重定向。这样的用法还是比较常见的,很多下载服务器可以通过这样的手段针对用户的权限做下载处理。

Flask

Flask是我喜欢的web框架,Flask甚至实现了一个 sendfile的方法,比上面的做法还简单。我用vagrant作了一个虚拟机,用Flask实现了上面的需求,具体代码如下:

项目结构


project struct

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

nginx的配置 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;
 }
 # 正常的静态文件
 location /static/(.*) {
   root /vagrant/;

}
 # 用户上传的文件,需要做权限限制
 location /upload/(.*) {
   alias /vagrant/;
   internal;    # 只接受内部请求的指令
 }
}

Flask 代码

app.py


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')

# 用户上传的文件视图处理,在此处返回请求给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)

简单部署


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


标签:Python,Nginx
0
投稿

猜你喜欢

  • vs code开发中语法正确但显示报错问题分析解决

    2023-08-05 11:54:26
  • python操作csv格式文件之csv.DictReader()方法

    2021-03-04 18:10:04
  • PHP实现的redis主从数据库状态检测功能示例

    2023-09-08 01:36:38
  • 详解MybatisPlus集成nacos导致druid连接不上数据库

    2024-01-18 02:57:09
  • 有关perl的内置特殊变量介绍

    2023-08-02 23:29:29
  • 如何用拦截表单的方法上传图片?

    2010-06-16 09:50:00
  • Python安装docx依赖包教程

    2023-02-11 22:23:36
  • Mysql的服务无法启动的1067错误解决

    2012-01-05 19:31:56
  • Python实现滑块验证码详解

    2022-03-15 09:04:53
  • Python实现K-means聚类算法并可视化生成动图步骤详解

    2021-06-20 23:10:40
  • Python代码列表求并集,交集,差集

    2021-12-03 03:33:38
  • Python3实现的爬虫爬取数据并存入mysql数据库操作示例

    2022-11-06 15:18:59
  • Python执行时间的几种计算方法

    2023-06-09 15:00:47
  • php ZipArchive解压缩实现后台管理升级问题详解

    2023-05-25 11:58:10
  • Python实现抖音热搜定时爬取功能

    2022-01-03 03:48:29
  • 关于ASP生成伪参数加密技巧

    2008-07-16 12:05:00
  • python import 上级目录的导入

    2021-09-13 00:54:29
  • python bluetooth蓝牙信息获取蓝牙设备类型的方法

    2023-08-23 00:57:16
  • python configparser中默认值的设定方式

    2023-09-08 22:01:33
  • Python解析命令行读取参数之argparse模块

    2021-12-17 22:15:32
  • asp之家 网络编程 m.aspxhome.com