{"action":"created","issue":{"url":"https://api.github.com/repos/eggjs/egg/issues/2187","repository_url":"https://api.github.com/repos/eggjs/egg","labels_url":"https://api.github.com/repos/eggjs/egg/issues/2187/labels{/name}","comments_url":"https://api.github.com/repos/eggjs/egg/issues/2187/comments","events_url":"https://api.github.com/repos/eggjs/egg/issues/2187/events","html_url":"https://github.com/eggjs/egg/issues/2187","id":303501991,"number":2187,"title":"[RFC] 给 ctx.request.body, ctx.request.query, ctx.request.params 增加一个类定义","user":{"login":"fengmk2","id":156269,"avatar_url":"https://avatars0.githubusercontent.com/u/156269?v=4","gravatar_id":"","url":"https://api.github.com/users/fengmk2","html_url":"https://github.com/fengmk2","followers_url":"https://api.github.com/users/fengmk2/followers","following_url":"https://api.github.com/users/fengmk2/following{/other_user}","gists_url":"https://api.github.com/users/fengmk2/gists{/gist_id}","starred_url":"https://api.github.com/users/fengmk2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fengmk2/subscriptions","organizations_url":"https://api.github.com/users/fengmk2/orgs","repos_url":"https://api.github.com/users/fengmk2/repos","events_url":"https://api.github.com/users/fengmk2/events{/privacy}","received_events_url":"https://api.github.com/users/fengmk2/received_events","type":"User","site_admin":false},"labels":[{"id":424351585,"url":"https://api.github.com/repos/eggjs/egg/labels/plugin:%20egg-security","name":"plugin: egg-security","color":"1C74D7","default":false},{"id":548697784,"url":"https://api.github.com/repos/eggjs/egg/labels/type:%20proposals","name":"type: proposals","color":"D4C5F9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":9,"created_at":"2018-03-08T14:38:42Z","updated_at":"2018-03-08T15:05:08Z","closed_at":null,"author_association":"OWNER","body":"## 背景描述\r\n\r\n由于这几个用户请求参数非常方便，开发者常常会偷懒，直接透传这些参数到 Model 层，直接作为 Model 层参数创建数据对象，然后保存的数据库。示例代码如下：\r\n\r\n```js\r\nctx.model.Post.create(ctx.request.body);\r\nctx.model.Post.update(ctx.request.query.id, ctx.request.body);\r\nctx.model.Post.destroy(ctx.request.params);\r\n```\r\n\r\n这样看起来代码很简单优雅，实际隐含着非常容易被攻击的可能性。如这 create 的时候，攻击者可以给 body 设置 id，强制修改你以为的自增长 id。\r\n\r\n这种模式违反了一个安全原则：不能信任一切用户输入的参数。\r\n\r\n## 解决方案\r\n\r\n借鉴 Rails 的 [StrongParameters](http://api.rubyonrails.org/classes/ActionController/StrongParameters.html) 思路，如果这些参数都是基于统一的 [Parameters](http://api.rubyonrails.org/classes/ActionController/Parameters.html) 参数类生产的参数对象，那么就可以这 Model 层的 create，update 和 destroy 各种数据操作方法里面，实现对参数判断，确保这些参数都不能够是 Parameters 类的对象实例。\r\n\r\n```js\r\nModel.prototype.create = function(params) {\r\n  if (params instanceof Parameters) throw new TypeError('wrong params');\r\n  // ...\r\n};\r\n```\r\n\r\n或者判断 `params.permitted`，总之需要给 Model 层知道参数是否原始用户参数，还是经过开发者处理过的参数。\r\n"},"comment":{"url":"https://api.github.com/repos/eggjs/egg/issues/comments/371513856","html_url":"https://github.com/eggjs/egg/issues/2187#issuecomment-371513856","issue_url":"https://api.github.com/repos/eggjs/egg/issues/2187","id":371513856,"user":{"login":"fengmk2","id":156269,"avatar_url":"https://avatars0.githubusercontent.com/u/156269?v=4","gravatar_id":"","url":"https://api.github.com/users/fengmk2","html_url":"https://github.com/fengmk2","followers_url":"https://api.github.com/users/fengmk2/followers","following_url":"https://api.github.com/users/fengmk2/following{/other_user}","gists_url":"https://api.github.com/users/fengmk2/gists{/gist_id}","starred_url":"https://api.github.com/users/fengmk2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fengmk2/subscriptions","organizations_url":"https://api.github.com/users/fengmk2/orgs","repos_url":"https://api.github.com/users/fengmk2/repos","events_url":"https://api.github.com/users/fengmk2/events{/privacy}","received_events_url":"https://api.github.com/users/fengmk2/received_events","type":"User","site_admin":false},"created_at":"2018-03-08T15:05:08Z","updated_at":"2018-03-08T15:05:08Z","author_association":"OWNER","body":"@huacnlee 核心原则就是要让 Model 感知参数是否经过开发者处理。"}}
{"actor":{"display_login":"fengmk2"}}