Rails 如何确保订单状态安全性

special · 2014年04月15日 · 最后由 comxtohr 回复于 2015年10月05日 · 4593 次阅读

最近做一电商系统,其中肯定包括了订单系统,订单表有一字段是当前订单状态,已用 strong_parameter 保护该字段。 但是客户认为还不够安全,担心黑客还能通过其它手段更改到订单状态字段,造成资金损失,要求对订单状态更改时,做一定的核验。 求教各位有何能确保订单状态安全性的手段?

客户担心的是你做的 😄

我乱讲 1、加 log 表、每次订单状态变更记录用户 id,ip 等。 2、某一金额之上的,如 1 万元之上的订单状态变更人工审核。 3、异常监视,一些非正常的事件(如经常有非法访问)的 ip 记录下来加入当天黑名单,在这些 ip 之上的订单状态变更也要人工审核。 4、在订单状态中,如果要变更到已付款的状态,付款的凭证比对等。 5、其他服务器安全性的要求。

哪有什么完全安全的程序,前几天支付宝还不是爆出 openSSL 的漏洞。 #2 楼 @5swords 人工审核这个方案不错,不过很多甲方希望程序又智能,又安全,帮你把方方面面都考虑全,然后你把这个平台建立好后,不需要人维护,傻钱多的客户就不断地涌入。因为我这个电商平台包含了甲方我无数的心血和创新,所以阿里和我比简直不值一提。 哦对了,这个项目报价太贵了,5 万是我承受的极限。

2 楼说的很全面了,再加一个状态机也有一定帮助。状态修改一定要符合一定顺序。a -> b -> c 不能直接 a -> c

@huacnlee 有道理

@special 订单状态直接设到订单 model(table) 里只能说是 demo 级的。最起码订单状态必须有 log。订单 id,user_id(谁改的)、状态、关联事项等等。谁、什么时候改的、改成什么状态、原因是什么,都必须有据可查。

订单表就是订单本身,不直接加状态栏。

读状态时,选关联 log 的最新状态。写状态不允许任何表单直接写。从业务上来说,状态也不是表单能增删改的东西。状态修改必须从属于某一个动作,比如说客户下单、仓库发货、等等。从这些动作里面来写状态。

这另一方面也增强安全性,只要你不刻意在订单 model 中明确表示接受状态的 nested_attributes,没人能直接从订单改。

修改订单锁死备货流程,走短信验证码通过后再恢复不就好了么?

或者效仿大部分电商不允许修改订单 (提供的修改功能仅仅是出库前改联系号码和送货地址), 要做货品变动取消了重新下单,已支付金额退回账户 (支付密码和登陆密码分离) 或者原路退回。

感谢楼上各位大大回复。 @5swords 第三点相当有启发 :plus1: @billy 订单状态 log 是有做的,但是只是拿来看,真没有在订单更改时对 log 做一些核验 :plus1: 受教。

另外有一个思路是每次更新时对订单表某些字段 + 订单状态字段联合起来进行不可逆加密存放到一个字段中,在读取订单状态时,再将当前订单的某些字段 + 订单状态不可逆加密后对比上面加密的字段,来确认状态是否被篡改,不知可否?

#7 楼 @special

当然好了,时间+状态+salt 作个 hash 应该就可以了,下次状态变更之前都校验一下。每天晚上出货之前,当天所有的状态变更成出货的全部验证一遍。

#3 楼 @bydmm 这个必须要赞一下啊,这样的客户真不少。

再怎么防也没办法防止直接改数据库

做好操作记录和对账,至于怎么对帐,这个请教会计比较好一点

涉及金额的运算,要使用事务,而不是 callback. 事务里,加上线程的保护: http://api.rubyonrails.org/classes/ActiveRecord/Locking/Pessimistic.html

#2 楼 @5swords log 表使用 MySQL 存怎么样?

#11 楼 @JeskTop 大多数 callback 就包装在同一个事务中的啊

#1 楼 @huacnlee 点赞

客户如果担心黑客,Linux、OpenSSL、IPTables、Nginx、Puma、Ruby、Rails、gems 以及应用代码任何地方都可能有漏洞

#13 楼 @HungYuHei 这样的吗? 但是如果像是 before_save 或者 after_save 的话,如果存 a 之后,update b 和 c。但是不要出现 a 存了,而 b 和 c 没有 update 的情况。

Model A < ActiveRecord::Base
  after_save do
    transaction do
      b.update!(xxx: xxx)
      c.update!(xxxx: yyyy)
    end
  end
end

像这样的情况,应该怎么把 A 也放到事务里?还是说都用around_save

@billy 请问对订单使用 log 记录状态,那应该如何获取某一状态的订单列表呢?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号