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>
打完收工。。。