# 07/26課堂筆記 ###### tags: `學長作業` `flask` `python` ## 練習準備 電腦要有[PostMan](https://www.postman.com/)和安裝好虛擬環境的專案目錄![](https://i.imgur.com/E2X59sR.png =70%x) app.py內我們先寫一個最基礎flask架構 ```python from flask import Flask, render_template app = Flask(__name__) # 啟用Debug app.config['ENV'] = "development" app.config['Debug'] = True @app.route("/") # 啟用路徑'/' def home(): return render_template("index.html") # 啟動Server app.run() ``` 我們在專案目錄內的templates目錄新增一個index.html檔案 ```htmlembedded <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>主畫面</title> <h1>我是主畫面</h1> </head> <body> </body> </html> ``` ## 1. json 資料傳遞 ### python code解釋與呈現 在app.py新增一段程式新增`request`物件 >![](https://i.imgur.com/aFl41g8.png) 在後面新增一個`/test5`的路徑 ```python @app.route("/test5", methods=["POST"]) # 新增一個可以傳遞Json格式的路徑 def jsonValue(): if request.is_json: # 判斷是否為JSON #判斷方式是根據 HTTP Header 的 Connect-Type有無application/json data = request.get_json() result = data.get('name', None) result = data.get('sex', None) result = data.get('ID', None) print(data) else: result = 'NO JSON Data' return result ``` ### Postman 操作 之後我們打開Postman按照下圖流程 1. 點擊Collections 2. 點選網址輸入欄旁的傳輸方法,這裡我們選POST 3. 輸入我們的網址路徑,我們這裡是用test5 4. 我們點選Body 5. 選擇Body底下的raw 6. 輸入格式我們選擇JSON 7. 輸入JSON格式的資料,資料的Key要對應到/test5的Key 8. 送出 * 操作如下 :arrow_down: >![](https://i.imgur.com/ZbH04Uz.png) 我們看一下結果(補充: python flask return 的格式只能是字串,所以把數字的雙引號拿掉就會出錯) >![](https://i.imgur.com/n7IK7Yl.png) 看一下我們剛剛使用`print(data)`的結果 :arrow_down: >![](https://i.imgur.com/fEe5hAB.png) 我們回到Postman,我們可以查看header的content-Type這裡會存我們傳送出去的資料格式 >![](https://i.imgur.com/VpmSFfU.png) ## 2. 檔案上傳 ### python code解釋與呈現 我們需要再`import`新的物件 :arrow_down: >![](https://i.imgur.com/iIUeYSN.png) > >![](https://i.imgur.com/8qQnqwU.png) 增加新的路徑 `/file-upload` :arrow_down: ```python @app.route("/file-upload", methods=["POST"]) def upload(): f = request.files['upload_img'] # 設定上傳檔案名稱 filename = secure_filename(f.filename) os.makedirs("./upload", exist_ok=True) # 確定會有upload目錄,沒有的話會自行創建 f.save(os.path.join("./upload", filename)) return "success" ``` ### Postman 操作 1. 我們輸入我們可以上傳檔案的網址路徑 2. 點選Body 3. 選擇form-data 4. 輸入與python對應的key名稱 5. 選擇上傳格式 6. 選擇File 7. 選擇要上傳的檔案 8. 送出 * 成功在Postman會看到Success * Vscode 會看到upload目錄以及我們上傳的圖檔 >![](https://i.imgur.com/8ds3HpV.png) >![](https://i.imgur.com/yL5kN6y.png) ## 3.Flask 回傳參數 - HTML Escape 避免有心人士利用[XSS攻擊](https://medium.com/hannah-lin/%E5%BE%9E%E6%94%BB%E6%93%8A%E8%87%AA%E5%B7%B1%E7%B6%B2%E7%AB%99%E5%AD%B8-xss-cross-site-scripting-%E5%8E%9F%E7%90%86%E7%AF%87-fec3d1864e42)網站 ### XSS演示 先新增一個有query String的路徑 ```python @app.route("/test01") def test1(): ans = request.args.get("input", "hello") return "ans is "+ans ``` >![](https://i.imgur.com/30BuCZ6.png) 如果我在網址打 ?input=`<script>alert('XSS test')</script>`會出現下面這種狀況,如果更嚴重可能會影響到整個網站的運作 >![](https://i.imgur.com/e5hOX0W.png) 所以我們需要學習使用HTML_Escape ### python code解釋與呈現 我們需要導入新的物件 >![](https://i.imgur.com/zepf8Kv.png) 我們在用escape把原本的code包起來 >![](https://i.imgur.com/OyHMPOO.png) 我們看一下結果: ![](https://i.imgur.com/Gz9Xt11.png) 如此一來可以簡單地避免掉一些有心人士的攻擊 ## 4.Flask 回傳參數 - JSON 我們可以利用json.dumps()達成 ### python code解釋與呈現 import JSON套件 ![](https://i.imgur.com/3rANvW8.png) 再新增一個路徑`/return_json` ```python @app.route("/return_json", methods=["POST"]) def retrun_json(): # 創建一個字典dict dict = { "name": "chichi", "sex": "male", "ID": 12345678 } return json.dumps(dict) ``` 我們會看到下圖結果醜醜的,而且被包成HTML >![](https://i.imgur.com/voCgmR5.png) >- >![](https://i.imgur.com/yK3e9gG.png) 那我們改成利用Flask內建的直接回傳字典,`return json.dumps(dict)`改為`return dict`,我們看看結果 >![](https://i.imgur.com/xdH4fjc.png) >![](https://i.imgur.com/KSKPbDg.png) 所以json.dumps()是將字典轉為字串~!而你直接回傳dictonary Flask會幫你改為字串!! ### 5.補充字串改JSON 可以利用flask的jsonfy >![](https://i.imgur.com/DqUdYDg.png) 用jsonify將字串包起來 >![](https://i.imgur.com/WQpHrLi.png) 看一下結果: >![](https://i.imgur.com/Y25lqAv.png) >- >![](https://i.imgur.com/c90CS9h.png) ## 之後可以補充一下 RESTful ## Flask cookie 紀錄一些不重要的數據,紀錄在前端使用者也可以查閱 ### python code解釋與呈現 我們需要導入make_reaponse物件 >![](https://i.imgur.com/ufIw1sm.png) 新增一個login路徑 >![](https://i.imgur.com/btYHyxC.png) 我們執行看看: >![](https://i.imgur.com/bHGNLP8.png =80%x) >-- >![](https://i.imgur.com/kRvFb7B.png =80%x) ## session 1. 開一個flask的基本程式,並創建一個/hello路徑 >![](https://i.imgur.com/PadYQ9X.png) 2. 我們看一下Server,good~ 有互動~ >![](https://i.imgur.com/O4SXfaB.png) 3. 再創建一個`/talk`路徑,疑??要怎麼記住name? >![](https://i.imgur.com/hK4KaCC.png) 4. 我們要載入session工具 >![](https://i.imgur.com/cPHMHj9.png) 5. 我們要設定密鑰 >![](https://i.imgur.com/V0PfP9R.png) 6. 我們要寫的應用,再`/hello`中存放我們得到的值 >![](https://i.imgur.com/vt4dPUK.png) 7. 解惑搂~我們在`/talk`中使用我們記住的`username` >![](https://i.imgur.com/LwksETI.png) ### 結果展示 ![](https://i.imgur.com/lQYbKM6.png) 直接進入`/talk`...你看成功了~ ![](https://i.imgur.com/Ef94rBS.png) ## 我的code Templates -> index.html ``` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>主畫面</title> <h1>我是主畫面</h1> </head> <body> <form method="post" action="/login"> 名字 : <input type="text" name="name"> <button>確定</button> </form> </body> </html> ``` Templates -> page.html ``` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>這是分頁</title> </head> <body> <h1>我是 {{ nameis }}</h1> </body> </html> ``` app.py ``` from flask import Flask, redirect, render_template, request, jsonify, make_response, template_rendered, url_for from flask import Response, url_for, session from werkzeug.utils import secure_filename import os from markupsafe import escape import json app = Flask(__name__) app.secret_key = "chichi" # 啟用Debug app.config['ENV'] = "development" app.config['DEBUG'] = True @app.route("/") # 啟用路徑'/' def index(): return render_template("index.html") @app.route("/test5", methods=["POST"]) # 新增一個可以傳遞Json格式的路徑 def jsonValue(): if request.is_json: # 判斷是否為JSON #判斷方式是根據 HTTP Header 的 Connect-Type有無application/json data = request.get_json() result = data.get('name', None) result = data.get('sex', None) result = data.get('ID', None) print(data) else: result = 'NO JSON Data' return result @app.route("/file-upload", methods=["POST"]) def upload(): f = request.files['upload_img'] # 設定上傳檔案名稱 filename = secure_filename(f.filename) os.makedirs("./upload", exist_ok=True) # 確定會有upload目錄,沒有的話會自行創建 f.save(os.path.join("./upload", filename)) return "success" # XSS TEST @app.route("/test01") def test1(): ans = escape(request.args.get("input", "hello")) return "ans is "+ans @app.route("/return_json", methods=["POST"]) def retrun_json(): # 創建一個字典dict dict = { "name": "chichi", "sex": "male", "ID": 12345678 } return dict @app.route("/jsonify", methods=["POST"]) def retrun_jsonify(): # 創建一個字典dict str1 = "I am String" return jsonify(str1) @app.route("/login", methods=["post", "GET"]) def login(): account = request.values.get('name', "chichi") response = make_response(render_template('index.html')) response.set_cookie('username', account) session['user'] = account return response @app.route('/session') def session_text(): name = session['user'] render_template("page.html", nameis=name) return render_template("page.html", nameis=name) # 啟動Server app.run() ```