国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python的Flask框架及Nginx實現靜態文件訪問限制功能

2019-11-25 16:41:31
字體:
來源:轉載
供稿:網友

Nginx配置

Ngnix,一個高性能的web服務器,毫無疑問它是當下的寵兒。卓越的性能,靈活可擴展,在服務器領域里攻城拔寨,征戰天下。

靜態文件對于大多數website是不可或缺的一部分。使用Nginx來處理靜態文件也是常見的方式。然而,一些靜態文件,我們并不像任何情況下都公開給任何用戶。例如一些提供給用戶下載的文件,一些用戶上傳的涉及用戶隱私的圖片等。我們我希望用戶登錄的情況下可以訪問,未登錄的用戶則不可見。

粗略的處理,在后端程序可以做過濾,渲染頁面的時候,在視圖邏輯里面驗證用戶登錄,然后返回對應的頁面。例如下面的flask代碼(偽代碼)

@app.router('/user/idcard'):def user_idcard_page(): if user is login:  return '<img src="http://files.VeVB.COm/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_requireddef 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 structproject 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 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')# 用戶上傳的文件視圖處理,在此處返回請求給nginx@app.route('/upload/<filename>')@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)

簡單部署

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 深州市| 平陆县| 崇礼县| 澳门| 奎屯市| 铁力市| 天水市| 定日县| 津市市| 临猗县| 灵石县| 塔河县| 黔南| 东丽区| 拜城县| 崇左市| 扬中市| 武冈市| 扎鲁特旗| 新巴尔虎右旗| 四平市| 睢宁县| 娄烦县| 龙门县| 原平市| 勐海县| 林周县| 新闻| 正定县| 万荣县| 仲巴县| 文水县| 定边县| 衡阳市| 贵溪市| 敖汉旗| 河西区| 崇文区| 通渭县| 闽清县| 固安县|