65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Azure 上符合 PCI 标准的信用卡处理

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (11投票s)

2013 年 4 月 29 日

CPOL

15分钟阅读

viewsIcon

49717

云端范围内外的支付处理

 引言  

我写这篇文章是为了参加 2013 年 Azure 挑战赛,但由于日程安排的变化,我不得不退出比赛,导致文章的长度和内容远未达到预期的目标。   这篇文章的最新版本只是为了整理现有内容;希望能将其转化为一篇关于 JavaScript 中符合 PCI 标准的支付处理的独立文章。   所描述的技术非常适用于 Azure 网站和其他云服务,但我从未进行过集成。  我会在日程安排允许的情况下尽快回来扩充这篇文章。 

本文将演示一种客户端、范围外的支付处理技术,适用于 Windows Azure 程序员。 

乍一看,在网站上收集信用卡信息似乎很简单。在您的网站上以 HTML 表单的形式显示必要的输入字段;然后将收集到的信息发布回您的服务器端代码,由服务器端代码将其传递给银行的网关,以换取大量金钱。  在一个完美且光明的世界里,这可能就是所有必需的,但在现实世界中,处理信用卡要复杂得多。 

支付卡行业数据安全标准 (PCI DSS) 规范了借记卡和信用卡信息的传输。网站、网站服务器和数据库存储设施在允许处理或存储持卡人信息之前,必须符合 PCI 标准。目前共有 12 项要求,并且需要进行昂贵的审计才能获得合规性。PCI 合规性的基本理念是,从收集的那一刻起,任何不合规的服务器或数据库都不得接触持卡人信息。如果接触了,整个过程将无效。 

Azure 本身不符合 PCI 标准。尽管其数据中心无论在物理上还是数字上都极其安全,但尚未获得所有必要的认证。因此,如果 Azure 服务器接触到收集到的持卡人信息……直接接触,您的网站就不能在 PCI 指南下处理信用卡。 

本文将演示一种客户端技术,用于处理和保留持卡人信息,而无需将这些信息发布回 Azure。相反,浏览器中的 JavaScript 会将敏感信息发布到一个符合 PCI 标准的数据存储库,该存储库在 Azure 网络之外。  数据存储库会在回复中返回一个令牌,代表单个持卡人与单个信用卡商之间的合同。  该令牌只能用于在这两个方之间转移资金。  它本身不包含持卡人或商户账户信息,也不能用于从数据存储库访问此类信息。    根据定义,敏感信息会进入数据存储库,并且永远不会返回;返回的令牌功能极其有限。  从 PCI 合规性的角度来看,它们不被视为敏感信息,因此 Azure 服务器可以接触它们,并将其存储在 Azure 数据库中,而不会损害其交易的合规性。 

信用卡行业提供了两个简略的术语来对处理信用卡持有人敏感信息的编程技术进行分类。 “范围之内”技术直接访问信用卡的号码、到期日期和 3-4 位安全码。  使用“范围之内”技术的 Web 服务器需要满足 PCI 合规性指南。  “范围之外”技术使用各种客户端技术,如跨浏览器 AJAX 发布和浏览器重定向,将敏感信息远离您的 Web 服务器;它们允许其他机器(如支付网关的服务器)执行“范围之内”的信息处理。  在此过程中,它们将大部分 PCI 合规性负担转移到该其他机器上。  本文将仅关注“范围之外”的解决方案,这些解决方案本质上可以安全地与 Azure 一起使用。 

概述 

为了演示这种客户端技术,我创建了一个简单的 MVC 网站 http://pay2see.azurewebsites.net,包含两个视图和一个控制器。   索引视图包含一个收集信用卡信息的表单和一个按钮,该按钮可以对提供的信用卡收取两美元的费用。  然后它会显示内部的“安全”视图。    此时没有模型或数据库,但将在下一个挑战中添加。  因此,这是一种用于“按次付费”场景的信用卡处理演示,在这种场景下,用户每次想要查看安全页面时都需要付费。  未来,我们将将其发展为“订阅”场景,即用户的一次付款允许他们多次查看。 

免责声明

  • 本文不是 SlimCD 的广告。  他们只是我使用的支付网关。  我听说 BrainTree Payments 和 Stripe 提供类似的功能,但我没有与他们合作的经验。 
  • 本文的 Azure 网站上的支付处理代码是完全功能的,能够进行真实世界的业务交易,收取真实的信用卡,并向真实的商户账户存入收入。  然而,本文的 Azure 网站配置了一个测试商户账户,因此当您测试该网站时,不会发生真实世界的业务,也不会涉及真实的金钱。 
  • 为了方便您测试该网站,索引视图的信用卡输入表单的许多字段已加载默认值。  这些值是假的,仅适用于为该网站设置的测试商户账户。 
  • 我不保证本文中的任何内容都是真实的。  我很确定我对支付处理的理解是当前最新的,并且这里描述的技术对于 PCI 合规性来说是范围外的。  请与您的 PCI 合规性专家或提供您商户账户的商户服务提供商/银行重新核实此处的所有内容。 

技术摘要

当索引视图的按钮被点击时,一个 JavaScript 函数首先验证所需字段是否已输入信息,然后将该信息跨浏览器发布到支付网关进行存储和标记化。  网关向 JavaScript 提供回复,提供一个交易令牌,该令牌会存储在表单的隐藏字段中。  然后 JavaScript 清除表单中的信用卡号和安全码输入字段,然后将表单提交给正在 Azure Web 服务器上等待的控制器。  如果 JavaScript 没有清除这些输入字段,那么我们现在将在 Azure 的范围内,这将违反 PCI 合规性。  由于 JavaScript 清除了这些字段,敏感信息在仍位于用户浏览器中时已被清除,因此 Azure 只能看到交易令牌。  这意味着我们的 MVC 控制器在 Azure 上运行,是范围外的。 

控制器现在使用交易令牌对关联的信用卡收取两美元的费用。  它通过向支付网关提交令牌的“processtransaction”请求来完成此操作。  如果网关确认充电成功,控制器然后将用户的浏览器更改为安全视图。  这实现了上述“按次付费”场景。 

如果充电过程中出现任何问题,例如卡无效或超出限额,控制器将向用户的浏览器重新发送索引视图,并附带一个描述问题的错误消息。 

在比赛的这一点上,这就是我们对交易令牌所做的全部工作;对其进行一次收费,然后将其丢弃。  在第三个挑战中,我们将持久化交易令牌,将其作为持卡人重新访问安全页面的权利的证明。  在第四个挑战中,我们将在一台虚拟机上设置一个 Web 服务,该 Web 服务将使用交易令牌定期向用户收费,以维持他们访问网站安全页面的订阅。  交易令牌是实现特定客户与特定商户之间持久且重复收费关系的极其有用的工具,我们将在本次比赛的后续挑战中进一步探讨。 

幕后 (客户端:索引视图)

此解决方案的核心是标记化步骤,而该步骤的核心是以下 JavaScript 函数。  此 JavaScript 是 Azure 网站索引页面的一部分,并在信用卡收集表单上的按钮单击时被调用。 

此 JavaScript 函数的亮点包括…… 

 

A)。 验证用户输入。  支付网关提供了一个 JavaScript 库,其中包含用于验证信用卡号、到期日期、支票路由号码和其他各种支付处理信息类型的例程。 

B)。 同一个 JavaScript 库包含一个名为 ProcessTransaction 的函数,它处理跨浏览器、AJAX 式的发布。  它接受一个 JSON 数组,其中包含商户账户信息、信用卡信息和一个非常重要的交易类型字段。  在此示例中,商户账户信息包括用户名、siteid 和 priceid 行,这些行是从字符串文字加载的。  信用卡信息直接从表单的输入加载,交易类型是字符串文字“LOAD”。 

C)。 “LOAD”是告诉信用卡网关存储提供的商户/信用卡信息并返回交易令牌供将来使用的命令。 

D)。 ProcessTransaction() 方法还接受一个附加参数,即 JavaScript“回调”函数。  该函数将在 ProcessTransaction 方法完成后执行,并将传递一个包含支付处理结果的回复对象。  在此示例中,回调函数用于清除敏感信用卡信息(E),并将交易令牌和其他一些支持信息存储在隐藏字段中(F)。  回调函数尝试的最后一件事是通过一小段 jQuery 将表单提交回其控制器(G)。  *(我曾试图在这个例子中避免使用任何除了最简单的 JavaScript 之外的东西,但在让我的非 jQuery 匿名表单提交代码正常工作时遇到了麻烦,所以我将其替换了。)* 

幕后 (服务器端:主控制器)

现在,我们的索引视图将发布回我们的控制器,其敏感字段已被清除,并且有一个名为“transactiontoken”的隐藏字段包含我们新创建的交易令牌。  到目前为止,我们只完成了数据标记化。  还没有移动任何金钱。 
下一步是执行实际的信用卡收费,这发生在服务器端,远离窥探的眼睛。  让我们看看主控制器的索引方法。 

这个 C# 方法接受来自 Index 视图的 POST 请求,然后,如果该视图传入了一个 transactiontoken 值,它将使用该令牌对关联的信用卡进行收费。  它通过调用 ProcessTransactions 方法的 C# 版本来完成此操作,这次使用 transtype 值“SALE”。  这个 transtype 实际上是对卡进行收费,而不是仅仅进行标记化。 

此控制器方法的亮点包括…… 

 

A)。 它从集合数组中接收交易令牌。  这之所以有效,是因为在视图中的 HTML 表单上,transactiontoken 隐藏字段有一个 name 属性。  ASP.NET MVC 在回发期间将命名的输入加载到集合数组中。  请注意,没有敏感信息输入具有 name 属性,因此它们在意外回发时不会传递到服务器。  交易令牌存储在 ProcessTransactionRequest 类的 gateid 字段中。 
注意:尽管支付网关很乐意提供多种编程语言的相同处理库,但每种都有点不同。  例如,javascript 中的 processTransaction() 的请求对象是一个 JSON 数组,而在 C# 中,它是一个正式类型的实例化类。  我在使用的每个版本的库中都有一些特定语言的风格,但底层的想法在整个库中保持一致。 

B)。 在 javascript 调用中,我们只加载了 username 字段,使用了一个特权非常低的访问令牌,该令牌只能运行 transtype 'LOAD'。  我们可以提供一个更强大的用户名/密码对,就像我们现在这样做一样,但这不符合最佳实践。  我将在下面的安全部分介绍原因。 

C)。 客户端交易参考是一个字符串,将与信用卡交易一起存储,并可能显示在持卡人的账单上。  它应该是一个唯一的标识符,客户在与商户讨论此交易时可以使用。  例如,客户可能会说:“您好,我想咨询一下我 1 月 3 日的信用卡购买,发票号 #10043……” 10043 就是客户端交易参考。  它不必对支付网关、信用卡提供商或银行有意义,但它应该对商户有意义,帮助他们准确识别这笔信用卡交易正在支付哪个事件。  在这个例子中,我只是使用了随机数,但在下一个挑战中会改变。 

D)。 这次,transtype 值是 'SALE',这意味着(如果我们没有使用测试商户账户)真实的金钱将从持卡人的银行转移到商户。  请注意,这也正是我们设置销售金额的地方,而不是在客户端,那里的黑客可能会对其进行篡改。 

E)。ProcessTransaction() 完成后,我们从回复类实例中提取返回值,并将它们加载到 viewbag 中。  我们即将调用的安全视图将这些返回值显示为简单的收据。 

F)。 如果 ProcessTransaction() 返回批准,我们将安全视图发送到客户的浏览器。 

G)。 如果没有,我们会更新错误消息,然后向他们发送另一份索引视图的副本。 
 

几句关于安全的话

对于单次交易,我们与支付网关通信两次,这似乎有点奇怪。  我们从客户端 JavaScript 调用网关一次,以标记化收集到的卡信息,但此时我们并没有实际收费。  然后,在服务器端,我们使用新创建的令牌执行实际的收费。  这项额外工作的原因可以用一个词来概括:安全。 

客户端的一切都是可见的:查看 JavaScript 示例 B 部分的第二行。  那是支付网关的访问凭证,是提交请求并以特定商户名义进行业务的密钥。  前往示例网站,右键单击任意位置,然后选择“查看源”。  您会发现完全相同的行,公开可见,供全世界查看。  当您查看暴露的其余源代码时,您会发现其他暴露的宝藏,例如 processTransactions() 端点,可以通过该端点输入交易。  只要有点恶意想法,就能想象由此产生的麻烦,直到您考虑到此处暴露的访问凭证几乎无能为力。 

客户端暴露的支付网关凭证是一个只会一种把戏的马……
它只能提交 transtype 为 'LOAD' 的请求。  所有其他 transtypes 都已在网关处关闭,将被忽略。   暴露的代码和值唯一能做的就是提交信息以进行标记化…… 

并且标记化是一个黑洞…… 
transtype 为“LOAD”的请求接受任何文本流,并且只返回一个令牌作为回复。  它们不对提供的信息进行验证,只返回一些易于计算的值,例如卡号的最后四位数字及其数学确定的卡类型。  令牌是返回的唯一可能有价值的信息片段,并且只有拥有同一商户账户上更高特权访问凭证的人才有价值。 

黑客从客户端暴露的信息中获取的任何东西,都无法帮助他们进行盗窃或恶作剧。 

在服务器端,安全地位于 Azure 的防护之下,可以尝试第二次调用支付网关,使用更高特权 ID。  那个更强大的凭证,那个可以实际执行销售的凭证,仍然安全地保存在服务器端,在第二个代码示例所示的控制器代码中。 

这种安排的完整性微妙但不可否认地美丽。  在客户端,在用户浏览器中,我们可以直接接触敏感的信用卡信息,但那里唯一的支付网关凭证仅限于标记化。  在服务器端,我们拥有可以转移真实金钱的凭证,但我们只有信用卡信息的令牌,并且它与网站所有者的商户账户绑定。  我们只能在单个信用卡和单个商户之间转移资金。  安排的任何一方都没有足够的信息来使其值得被闯入。  只有在双方实时且瞬息的同步中,才有商业机会,即使如此,也只能在持卡人与他们打算光顾的商户之间进行。 

任何一方都不会为潜在的窃贼提供值得窃取的东西。 

还有其他原因可以分割活动,但我不想将本文变成黑客的教育资源。  与许多安全问题一样,试图警告潜在的受害者往往会起到教育犯罪者的作用。  在暴露比绝对必要更多的信息之前,请与您的支付网关服务提供商讨论这些问题,即使如此,也要定期审查您的安全暴露情况是否存在漏洞。 

结语 

 

祝所有留在 Azure 挑战赛中的人好运! 
与大家同场竞技,也与大家成为对手,都非常愉快! 

 

- Colt  

© . All rights reserved.