编码/混淆HTTP参数

我们目前正在开发一个非常简单的Web应用程序,我们希望“混淆” (什么是正确的术语?)或以某种方式编码请求参数,这样我们就可以减少空闲用户发送任意数据的机会。

例如,url看起来像/webapp?user=Oscar&count=3

我们想要像/webapp?data=EDZhjgzzkjhGZKJHGZIUYZT并在服务器中使用真实的请求信息解码该值。

在我自己实现这样的事情之前(并且可能做错了)我想知道是否有什么事情可以做到这一点?

我们在服务器上有Java,在客户端上有JavaScript。

不,不要这样做。 如果你可以在客户端代码中构建一些东西来混淆传输回服务器的数据,那么一个故意的黑客也是如此。 无论您的官方客户端做什么,您都无法信任发送到您服务器的数据。 坚持逃避客户端数据并根据服务器端的白名单进行validation 。 使用SSL,如果可以,请将请求参数放在POST而不是GET中。

扩展编辑

您的困惑源于阻止用户篡改请求数据的目标,需要实施标准安全措施。 Web应用程序的标准安全措施涉及使用身份validation,权限和会话管理,审计跟踪,数据validation和安全通信渠道的组合。

使用SSL并不会阻止客户端篡改数据,但它确实阻止了中间人看到或篡改它。 它还指示行为良好的浏览器不要在URL历史记录中缓存敏感数据。

看起来你有一些没有身份validation的简单Web应用程序,并传递在GET中控制它的请求参数,因此一些非技术上精明的人可能会发现user=WorkerBee可以简单地改为user=Boss在他们的浏览器栏中,因此他们可以访问他们不应该看到的数据,或做他们不应该做的事情。 你对这些参数进行模糊处理的愿望(或顾客的愿望)是天真的,因为它只能挫败技术上最不精明的人。 这是一个半生不熟的措施,你没有找到现有解决方案的原因是它不是一个好方法 。 你最好花时间实现一个体面的认证系统和审计跟踪(如果确实如此,那么将Gary的答案标记为正确)。

所以,把它包起来:

  1. 混淆的安全性根本不是安全性。
  2. 您无法信任用户数据,即使它被遮挡了。 validation您的数据 。
  3. 使用安全通信通道(SSL)有助于阻止其他相关威胁。
  4. 你应该放弃你的方法,做正确的事。 在您的情况下,正确的事情可能意味着添加一个带有权限系统的身份validation机制,以防止用户访问他们没有足够的特权来查看 – 包括他们可能通过篡改GET参数尝试访问的内容。 Gary R的回答 ,以及Dave和Will的评论都击中了这一点。

如果您的目标是“减少空闲用户发送任意数据的机会”,那么我会尝试另一种更简单的方法。 创建一个私有加密密钥并将其存储在应用程序服务器端。 每当您的应用程序生成URL时,使用您的私有加密密钥创建URL的哈希值,并将该哈希值放入查询字符串中。 每当用户请求包含url参数的页面时,重新计算哈希并查看它是否匹配。 这将使您确定应用程序计算了URL。 它会使您的查询字符串参数可读。 在伪代码中

 SALT = "so9dnfi3i21nwpsodjf"; function computeUrl(url) { return url + "&hash=" + md5(url + SALT ); } function checkUrl(url) { hash = /&hash=(.+)/.match(url); oldUrl = url.strip(/&hash=.+/); return md5(oldUrl + SALT ) == hash; } 

如果您尝试限制对数据的访问,则使用某种登录机制和cookie,提供单点登录身份validation密钥。 如果客户端使用密钥发送cookie,则他们可以根据与其帐户相关联的权限(管理员,公共用户等)操纵数据。 只需看看Spring Security,CAS等,就可以在Java中轻松使用它。 cookie中提供的令牌通常使用发布服务器的私钥加密,并且通常是防篡改的。

或者,如果您希望公共用户(未经身份validation的)能够将某些数据发布到您的网站,那么所有投注都将被取消。 您必须在服务器端validation。 这意味着限制对某些URI的访问并确保清除所有输入。

这里的黄金法则是禁止一切,除了你认识的东西是安全的。

如果目标是防止“静态”URL被操纵,那么您可以简单地加密参数或签名。 它可能“足够安全”来处理URL参数的MD5以及一些盐。 例如,盐可以是存储在会话中的随机字符串。

然后你就可以:

 http://example.com/service?x=123&y=Bob&sig=ABCD1324 

这种技术暴露了数据(即他们可以“看到”xyz = 123),但他们不能改变数据。

有一个“加密”的优点(我松散地使用这个术语)。 您可以在此处加密URL的整个参数部分。

在这里,您可以执行以下操作:

 http://example.com/service?data=ABC1235ABC 

使用加密的好处是双重的。

一个它保护数据(例如,用户永远不会看到xyz = 123)。

另一个特点是它是可扩展的:

 http://example.com/service?data=ABC1235ABC&newparm=123&otherparm=abc 

在这里,您可以解码原始有效负载,并与新数据进行(安全)合并。

因此,请求可以向请求添加数据,而不是更改现有数据。

您可以通过签名技术执行相同的操作,您只需要将整个请求合并到一个“blob”中,并且该Blob是隐式签名的。 这是“有效”加密的,只是一种弱加密。

显然你不想在客户端做任何这样的事情。 毫无意义。 如果你能做到这一点,“他们”可以做到而且你无法区分,所以你可能根本就不去做 – 除非你想通过普通的HTTP端口“加密”数据(对TLS,但随后人们会明智地想知道“为什么要打扰”)。

对于Java,所有这些工作都在Filter中,这就是我的方式。 后端与此隔离。

如果您愿意,可以使用在出路时处理URL加密/签名的出站filter使后端与此完全隔离。

这也是我做的。

不利的一面是它使得它正确且高效。 你需要一个轻量级的HTML解析器来提取URL(我写了一个流解析器来实现它,所以它没有将整个页面复制到RAM中)。

光明的一面是所有内容方面“正常工作”,因为他们对此一无所知。

在处理Javascript时还有一些特殊处理(因为您的filter不会轻易“知道”哪里有加密的URL)。 我通过要求将URL标记为特定的“var signedURL =’….’”来解决这个问题,因此我可以在输出中轻松找到它们。 并不像你想象的那样压倒设计师的负担。

filter的另一个亮点是你可以禁用它。 如果您发生了一些“奇怪的行为”,只需将其关闭即可。 如果行为继续,您发现了与加密相关的错误。 它还允许开发人员以纯文本forms工作,并保留加密以进行集成测试。

痛苦,但总体来说总体上还不错。

像jCryption这样的东西?

http://www.jcryption.org/examples/

您可以使用base64或类似的东西对数据进行编码。 我会在JSON中编码自身的参数来序列化它们。