1、eggjs post提交數據
在eggjs如何接受用戶提交的post數據呢?javascript
①:在routerjs中新建兩個路由規則:html
router.get("/doLogin", controller.login.doLogin); router.post("/userLogin", controller.login.getUserData);
第一個訪問/doLogin,執行login controller下的doLogin方法,渲染login頁面。java
第二個訪問/userLogin,執行login controller下的getUserData方法,打印接收的post數據。git
②緊着着編寫login controller,注意:在eggjs中可使用ctx.request.body來獲取用戶post的數據。github
"use strict"; const Controller = require("egg").Controller; class LoginController extends Controller { async doLogin() { const { ctx } = this; await ctx.render("login"); } async getUserData() { const { ctx } = this; console.log(ctx.request.body); } } module.exports = LoginController;
③view下新建login頁面,寫一個簡單登陸表單,咱們的想法是點擊登陸匹配userLogin路由,執行login controller下的getUserData方法,打印接收的post數據。瀏覽器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>登陸頁面</title> </head> <body> <form action="/userLogin" method="POST"> 用戶名:<input type="text" name="username"><br/> 密碼:<input type="password" name="password"><br/> <button type="submit">登陸</button> </form> </body>
④訪問/userLogin,看到登陸頁面,點擊登陸按鈕。安全
而後呢,咱們會看到以下界面:報了個403的錯誤 什麼invalid csrf token,這是個什麼鬼東西哦?????服務器
按照官方介紹說的 eggjs內置了 csrf安全機制,下面是copy了官網上的描述:csrf攻擊:僞造用戶請求向網站發起惡意請求。app
Web 安全概念
Web 應用中存在不少安全風險,這些風險會被黑客利用,輕則篡改網頁內容,重則竊取網站內部數據,更爲嚴重的則是在網頁中植入惡意代碼,使得用戶受到侵害。常見的安全漏洞以下:框架
- XSS 攻擊:對 Web 頁面注入腳本,使用 JavaScript 竊取用戶信息,誘導用戶操做。
- CSRF 攻擊:僞造用戶請求向網站發起惡意請求。
- 釣魚攻擊:利用網站的跳轉連接或者圖片製造釣魚陷阱。
- HTTP參數污染:利用對參數格式驗證的不完善,對服務器進行參數注入攻擊。
- 遠程代碼執行:用戶經過瀏覽器提交執行命令,因爲服務器端沒有針對執行函數作過濾,致使在沒有指定絕對路徑的狀況下就執行命令。
而框架自己針對 Web 端常見的安全風險內置了豐富的解決方案:
- 利用 extend 機制擴展了 Helper API, 提供了各類模板過濾函數,防止釣魚或 XSS 攻擊。
- 常見 Web 安全頭的支持。
- CSRF 的防護方案。
- 靈活的安全配置,能夠匹配不一樣的請求 url 。
- 可定製的白名單,用於安全跳轉和 url 過濾。
- 各類模板相關的工具函數作預處理。
在框架中內置了安全插件 egg-security, 提供了默認的安全實踐。
⑤在渲染頁面的時候傳入生成的csrf給頁面
async doLogin() { const { ctx } = this; // this.ctx.csrf 當用戶訪問頁面,會生成一個簡單地祕鑰,用戶調用接口需將這個祕鑰傳回去,防止他人屢次惡意不停的掉接口 await ctx.render("login", { csrf: this.ctx.csrf }); }
⑥在頁面上拿到csrf作以下改動:
⑦可觀察到dom面板中csrf渲染的值,這個值,每次刷新頁面的時候都會變,點擊登陸按鈕,發現控制檯打印出post的數據
點了兩下,因此打印出了兩下。
到此,咱們就獲取到了用戶簡單post提交的數據。
有個小問題就是,當咱們想在不少controller裏面的不少post請求都要傳遞這個csrf每次都要寫這個csrf:this.ctx.csrf,太麻煩了,eggjs爲咱們提供了定義模板全局變量的途徑:在中間件中設置全局變量
①:middleware下新建auth.js,鍵入以下內容:
module.exports = (option, app) => { return async function auth(ctx, next) { // 設置模板全局變量 ctx.state.csrf = ctx.csrf; await next(); }; };
②在config>config.default.js中進行中間件配置掛載
③全局變量配置好了以後,將剛纔在controller中傳入的csrf值刪掉,看模板的csrf有沒有做用或者報錯,會發現,csrf驗證依舊可用。則模板全局變量配置完成。
④模板添加csrf還有一種寫法是隱藏表單域傳值:點擊登陸發現csrf驗證依舊生效。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>登陸頁面</title> </head> <body> <form action="/userLogin" method="POST"> <input type="hidden" name="_csrf" value="<%=csrf%>"> 用戶名:<input type="text" name="username"><br/> 密碼:<input type="password" name="password"><br/> <button type="submit">登陸</button> </form> </body>
打完收工。。。