我正在设计Flex中的应用程序,该应用程序连接到某些Web服务以执行一些金融交易.Web服务使用https协议进行保护,并要求在每次请求时登录时创建用户令牌.这用于验证和授权用户.到现在为止还挺好.
诀窍在于,并非所有的Web服务都是粗粒度的.举个例子,我们可以有两种Web服务方法:EnoughFounds和Transfer.因此,只有在方法EnoughFounds回复"true"之后,才会执行Transfer.此逻辑在Flex应用程序代码中编程.
我呈现的场景如下:如果有人下载应用程序并对其进行反编译会怎样.然后修改代码,以便不执行步骤EnougFunds.或者也许写一个全新的客户端甚至可能在其他技术中执行Transfer而不通过EnoughFunds步骤.在执行Transfer时,将在服务器上授权和验证用户; 但由于他正在使用他的真实证书,他将能够执行转移.他跳过的检查属于业务逻辑而不属于安全域.我需要以某种方式确保执行应用程序的代码是未修改的我编写的Flex代码和用户下载的代码.我怎样才能做到这一点?我知道我可以重写服务,以便在服务器上执行序列,
在我看来,必须有一些安全机制来解决这个特殊问题.
请注意,我不是在寻找有关最佳实践的建议.我的要求是不要在服务器端改变任何东西.如何在不更改服务的情况下保护协议级别的序列?
这是一个大错误.必须在服务中检查任何重要的业务规则.必须是这样的,无论客户端做什么,服务都不会让任何不好的事情发生.
特别是,有一个EnoughFunds操作是有道理的,因为如果EnoughFunds返回false,你可以告诉用户他没有足够的资金.但是,转移操作必须检查是否有足够的资金,而不是依靠客户进行这种重要的检查.
让我加入这一点 - 我让孩子们反编译我的游戏并通过操纵http通信的工具来改变/编辑来回发送的消息 - 这只适用于没有外部价值的游戏.我的用户实际上加载了fiddler和firefox标头工具来操纵服务调用,只是为了在每天重置自己的游戏板上获得高分.
我不禁想到如果我把金钱或"真正的"价值投入到混合中会发生什么.
不要不相信客户端发送给你的任何数据...使用"enoughFunds"打电话来更新您的用户界面,但这样做的"转移"时阶段,你需要在服务器端完全重新评估该呼叫-不信任这只是因为客户要求转移你应该接受它.
如果不改变服务器端,就无法解决这个问题,因为正如所有其他答案都指出的那样,问题出在那里.此外,没有合适的协议也不会涉及更改服务器端.
将此与银行柜台的人进行比较是非常合适的.那个人向银行员工提交了一些凭证,证明她是谁以及她实际上拥有一些账户X.这就是登录.
现在,这个人想订购从账户X到Y的转账.无论她对可用资金说什么都不重要.如果她提交了银行总裁签署的文件说她有足够的资金,那么银行仍然需要在转账之前进行检查,因为钱只需要在那里.
这意味着,即使你在协议中得到一个安全的序列逻辑,确保在"转移"之前调用"EnoughFunds",并且只调用一次,不久之前,并且使用正确的参数,它仍然是客户端告诉银行"没关系,我有足够的资金".永远不会削减它.
你可以得到的最接近的是相当于靠在柜台上的银行客户,指着员工的屏幕并说"看,在这里,在你的系统中,它说交易可以完成,因为有足够的资金",即客户端可以可验证地重现服务器刚刚制作的 EnoughFunds调用的时间,输入和输出,这是可以的,但是毫无意义.
因此,解决方案是在内部使用转移调用EnoughFunds,期间.如果客户需要知道,您可以在没有足够资金的情况下返回描述性异常/错误.
就像这样.http://www.userfriendly.org/cartoons/archives/09mar/uf012514.gif
老实说,我认为你需要认真重新评估你的发展计划.正如其他人如此正确地陈述,您不能依赖客户的诚信.
简而言之,在您可以控制的环境之外没有 "安全,可靠的代码"之类的东西(即服务器 - 即便如此,它也是有争议的).你根本不知道你正在与之交谈的软件,所以无论你如何"调整"一个应用程序层协议,你仍然无法保证一个坏的演员不会简单地用反向工程实现欺骗你你的'调整'协议.
您的"信任域"仅扩展到Web服务api,不再进一步.如果您的服务无法验证其操作的完整性,那么它是一个设计糟糕的服务.