Maison >développement back-end >tutoriel php >会员删除自已的帖子时,两种做法那一种比较好呢?

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

WBOY
WBOYoriginal
2016-06-06 20:10:50868parcourir

比如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 指正

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

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

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

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

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

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn