欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

会员删除自已的帖子时,两种做法那一种比较好呢?

程序员文章站 2022-05-22 20:29:28
...
比如id为100的会员 要删除id为1000的帖子
有两种删除方案
1.SELECT user_id FROM post WHERE id = 1000
然后判断 user_id 是否 100 是的话就删除
2.DELETE FROM post WHERE id=1000 AND user_id=100
效率肯定是第二种高,但是第一种的灵活性比较好
如果user_id 不是100的话,说明id 100的会员绝壁不是善类,然后做日志

你们平时都是用哪一种?

回复内容:

比如id为100的会员 要删除id为1000的帖子
有两种删除方案
1.SELECT user_id FROM post WHERE id = 1000
然后判断 user_id 是否 100 是的话就删除
2.DELETE FROM post WHERE id=1000 AND user_id=100
效率肯定是第二种高,但是第一种的灵活性比较好
如果user_id 不是100的话,说明id 100的会员绝壁不是善类,然后做日志

你们平时都是用哪一种?

题主的需求是很明确的:

  1. 删帖请求需要验证 + 鉴权

  2. 验证:请求者是系统中任意一个合法用户即可

  3. 鉴权:要求帖子的user_id与请求者的用户ID相等

  4. 我们假设验证这一步题主搞定了,这里只讨论鉴权的问题

从这个意义上分析两个方案:

方案1

“获取数据(SELECT)--检查数据(做鉴权)--执行请求(DELETE)”,这个流程本身是没错的。事实上这个方案也更加的推崇。因为这样能够:

  1. 如果请求中途某一步失败,能够准确识别失败的理由

  2. 保留更多的灵活性,如果以后鉴权逻辑更复杂了,可以比较方便的增补

唯独需要注意的是要防止这个流程的原子性被破坏,例如:

  1. 程序执行 SELECT

  2. 其他请求执行了 UPDATE ,这条记录被更改了,造成鉴权本应失败(例如对应的条目转移给了其他用户)

  3. 程序仍以修改前的记录鉴权,此时本应失败的鉴权能够成功

  4. 程序错误的执行删除操作

你可能需要数据库事务一类的手段,保证这个请求的所有步骤收工之前,所涉及的记录不会由于其他原因被意外地改写。

方案2

方案2一个语句内搞定鉴权和删除两步操作,安全性和原子性上没有任何问题。成功就是成功,失败就是完全的失败,也不会发生数据前后的不一致。

但这个方法在API设计的原则上有一个致命的漏洞在于:如果出错,那么你只能知道删除了 0 行,而不能识别这个错误的原因是记录不存在,还是用户无权删除此记录。后台只能笼统地返回“处理请求出错”,就连返回 HTTP 400 还是 HTTP 403 都不能确定。

请求本身无效和用户没有权限,是性质完全不同的两件事,在错误提示和后续逻辑上一般差别很大。后台如果做了如此乱来的设计,会让前端无法做人的。

请不要做出这样的设计。

随便提几句

另外致某些答主:一切阻拦用户发出请求的前端手段都是徒劳的!你不能阻止:

  • 【被删除的内容1】

  • 用户在打开页面时有权,而后权限由于某些原因被收回了,但用户的浏览器上仍然显示着此页面

绝对不能假设用户的输入是可靠的,后台设计的这个原则绝对不得越雷池一步!没有任何的借口!

一些基础概念

  1. 判断一个动作能否执行,一定要通过“验证”(authentication)和“鉴权”(authorization)两道关口。“验证”检查操作者是不是他声称的这个用户;“鉴权”表明这个用户是否有执行某项动作的权利。

  2. 二者缺一不可。在实务上,有些动作的“鉴权”很简单甚至没有,但这必须是程序设计者思考过后,故意设计如此才可以接受,绝对不可以主观忽略掉不想。

  3. “验证”和“鉴权”必须先验,绝对不能过后追究。(数据破坏后再回滚的代价是非常高的!)


最后需要特别提到的是:题主对于鉴权不通过的请求进行日志记录,这是一个非常好的提法。事实上反复鉴权失败的用户,与其说是攻击者,倒不如说更有可能是被黑客盗号却浑然不知的“肉鸡”。

通过记录鉴权失败,来积累用户可疑程度的数据。用户的可疑性提高到一定程度后,暂时封号,并强制要求用户本人识别手机/密保问题来解封账号、重置密码,这是一个提高账号系统安全性的很有意义的做法。


【被删除的内容1】=“攻击者使用自动化浏览器工具(Selenium等)发出请求——这个你就算上了CSRF也防不住”
CSRF防不住非法请求是站不住脚的,感谢 @shenyangyeshuai 指正

删除失败了不可以做记录吗?失败无外乎两种,第一种就是删除别人的id文章,第二种就是用户id有问题,那么都可以归结为用户的id问题,所以还是用第二种吧

采用第二种,主要是效率,特别是数据量大的时候。即使100不是善类,对数据库的数据也不会产生影响

SQL语句改成这样:
DELETE FROM post WHERE user_id=100 AND id=1000
如果考虑做日志的话,直接在这个之前做权限验证,而不是在删除的时候做判断

我用phalcon框架,phalcon走的是第一种的路子。
主要的考虑点应该是在于model的设计,model上有验证,有事件,所以需要查出model出来,然后再删除。

如果系统做的完善的话,建议用第一个,给个记录,超过几次就封号,网络上坏人还是很多的