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
猜你喜欢
- ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1分组,在分组内部根据
- Dreamweaver快捷键大全,记住一些常用的快捷键会大大提高你的网页设计效率,如果你都使用快捷键,那么如果你去面试工作就容易被录取,呵呵
- 问题:如果一个网站拥有两个域名:domain1.com和domain2.com。在网站运营前期,主推domain1.com,但发展到中期,由
- 今天萌发一个想法,用css来实现透视效果。起初,我想到的是我们常见的添加阴影效果的方法,用多个div通过偏移来实现,但这需要很多 div,不
- 今天来说说鄙人对input输入框在处理上的细节处理和心得,其实制作一个符合CSS标准、FF/IE7/IE6等主流浏览器全兼容、符合用户体验的
- RegMail是用来存放注册邮件的表,现以创建时间(CreateTime)字段来给表进行分区,具体步骤如下:--为分区创建存储文件 
- 人们对于那些抄袭模仿的网站有诸多抱怨,但在这篇文章中,却没有冷嘲热讽的意思。但正如他们所说,“模仿是最为忠诚的奉承形式”。“如果你确实需要借
- 最近一直在研究 Javascript 相关的技术。在《Javascript 高级程序设计》有篇章节着重阐述了优化 Javascri
- 有个帖子写的检查全角的 <script> fun
- 一。存储过程的创建和使用1.创建程序包,并在程序中创建存储过程create or replace PACKAG
- 元素浮动导致的问题及解决办法大家都应该很熟悉了,举个简单的例子:<style type="text/css">
- Jaslabs的Justin Silverton列出了十条有关优化MySQL查询的语句,我不得不对此发表言论,因为这个清单非常非常糟糕。另外
- 如何用ASP获知机器的网络配置?看看我们的例子:Option Explicit Dim WSHShell&nb
- 在MySQL中,一个字符串中,如果某个序列具有特殊的含义,则这个序列以反斜线符号(‘\’)开头,称为转义字符。常见的转义字符:\0 ASCI
- 最近Google Code推出了一个面向网站开发者的 * Google DocType。它来自于网站开发者同时又面
- asp禁止站外盗链,站外提交方法、以及asp判断星期几方法.防盗链,主要通过判断上一页面来源是否是本站来实现的,不是本站的链接就
- 我一直不很明白在中国国内流行的设计风格,象在国外的很多地方都有鲜明的设计大方向,比如韩国站点设计一般比较花哨,所以动画很多,我们常常看到韩国
- 原文:http://www.smashingmagazine.com/ ... emarkable-favicons/翻译:Blank(怿飞
- 执行时间方法1import datetimestarttime = datetime.datetime.now()#long running
- 概要:Oracle关系数据库系统以其卓越的性能获得了广泛的应用,而保证数据库的安全性是数据库管理工作的重要内容。本文是笔者在总结Oracle