如果目标是防止“静态” 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,所有这些工作都在一个过滤器中进行,我就是这样做的。后端与此隔离。
如果您愿意,您可以使用出站过滤器使后端与此完全隔离,该过滤器在出站时处理 URL 加密/签名。
这也是我所做的。
不利的一面是,要使其正确且高效,需要非常复杂。您需要一个轻量级的 HTML 解析器来提取 URL(我编写了一个流式解析器来即时执行此操作,因此它不会将整个页面复制到 RAM 中)。
好的一面是所有内容方面都“正常工作”,因为他们对此一无所知。
在处理 Javascript 时还有一些特殊处理(因为您的过滤器不会轻易“知道”哪里有要加密的 URL)。我通过要求将 url 签名为特定的“var signedURL='....'”来解决这个问题,因此我可以在输出中轻松找到它们。不像你想象的那样给设计师带来沉重的负担。
过滤器的另一个亮点是您可以禁用它。如果您发生了一些“奇怪的行为”,只需将其关闭即可。如果该行为继续存在,则您发现了与加密相关的错误。它还允许开发人员以纯文本形式工作,并将加密留给集成测试。
做起来很痛苦,但总体来说还是不错的。