【问题标题】:How do I verify from a servlet that the connection was made with two-way SSL?如何从 servlet 验证连接是使用双向 SSL 建立的?
【发布时间】:2012-10-29 20:26:20
【问题描述】:

我编写了一个 servlet 过滤器来为 Web 应用程序增加安全性。在某些情况下,我想验证与应用程序服务器的连接是通过双向 SSL (TLS 1.0) 建立的。通常这是通过HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") 完成的;但是,在我的情况下,应用程序服务器前面有一个反向代理,该代理通过WL-Proxy-Client-Cert 标头将客户端证书传递给应用程序服务器。因此,当我检索上述属性时,我得到了最初出现在标头中的客户端证书。我要做的不仅是验证客户端证书,还要确保反向代理和应用程序服务器之间的连接受到双向 SSL 的保护。有没有办法让我从 servlet 进行此验证?我正在使用 WebLogic 10.3.4、Java EE 5。将 WebLogic SSL 端口配置为需要双向 SSL 不是一种选择,因为同一台服务器上的一些其他服务只需要单向 SSL。

【问题讨论】:

  • 您的应用服务器的所有连接都来自反向代理吗?如果是这样,您可以在应用服务器上要求双向 SSL。从浏览器到代理的某些连接可能不使用双向 SSL,但您可以确保从代理到应用服务器的所有连接都使用。
  • 嗯,实际上有两个反向代理(面向两个不同的供应商):一个代理通过单向 SSL 连接,另一个通过双向 SSL。我已经提出让两个代理都使用双向 SSL 连接到应用程序服务器的想法,但这个想法尚未被接受(目前)。除非必须,否则我们宁愿不管理额外的 SSL 证书。

标签: java servlets ssl weblogic x509


【解决方案1】:

无论客户端是网络浏览器还是您的反向代理,检查客户端证书都是一样的。只需获取 "javax.servlet.request.X509Certificate" 属性并检查它是否与您的反向代理匹配(基于 DN 或颁发者)。

WL-Proxy-Client-Cert 只有在验证提交给应用服务器的证书是代理的证书后,才在应用服务器想知道提交给代理的客户端证书时才起作用。

【讨论】:

  • 问题是有人可以绕过反向代理,获取反向代理的 X.509 证书的公钥,然后使用单向 SSL 连接到 WebLogic 服务器并发送反向代理的公钥通过WL-Proxy-Client-Cert 标头。我们已经测试了这个场景,它可以欺骗应用服务器。我们希望确保阻止此类请求,同时允许合法请求通过。
  • @vor 所以你只需要 (1) 阻止使用代理的证书:换句话说,禁用代理和服务器之间的 HTTPS,并且 (2) 禁用对服务器的直接访问。
  • 禁用 SSL 不是一种选择,因为我们需要对整个通信路径进行加密。
  • WL-Proxy-Client-Cert 标头中查看代理证书没有任何意义。该标头告诉您谁连接了代理。 javax.servlet.request.X509Certificate 属性告诉您谁连接到了应用服务器。使用X509Certificate属性验证连接应用服务器的客户端真的是代理,然后你就可以相信它给你的WL-Proxy-Client-Cert属于连接代理的用户。
  • 所以 Weblogic 会自动用WL-Proxy-Client-Cert 的值覆盖javax.servlet.request.X509Certificate 属性?啊。看看你是否可以configure it 不要像那样对你的应用撒谎,或者至少在用代理用户的证书替换它之前对真实(代理)证书进行自己的验证。
【解决方案2】:

您将在使用HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") 的过滤器中的原始请求中获得应用服务器所看到的证书:这将是反向代理自己的客户端证书,如果它正在使用的话。

根据您的要求,您可以根据需要根据此属性做出与授权相关的决策。您不需要验证您是否信任证书本身,因为身份验证应该由应用程序服务器的 SSL 连接器完成(配置了适当的信任库)。

您的容器中的大多数应用程序可能会期望 getAttribute("javax.servlet.request.X509Certificate") 引用用户的证书,而不是代理的证书。

尚不清楚您以哪种格式获取 WL-Proxy-Client-Cert 附加标头的值,但我会假设一些 PEM 格式。 您应该能够转换此内容并将其放入过滤器中的javax.servlet.request.X509Certificate 属性中,然后才能到达您的过滤器/逻辑的其余部分。这应该是代表证书链的java.security.cert.X509Certificate 数组(首先是客户端证书,然后是颁发者)。您可以使用 CertificateFactory(参见示例)或 BouncyCastle 的 PEMReader 进行转换。

您可以在那里验证这些证书,但我想说这样做没有什么意义。当用户和代理之间的连接完成时,这应该在反向代理中完成。如果您不信任代理,它仍然可以向您发送它想要的任何证书:您将无法从工作节点检查用户是否拥有该证书的私钥,只有反向代理可以做到这一点。

话虽如此,您当然可以使用通过这种方式获得的客户端证书做出授权决定(同样,前提是您信任反向代理:出于这个原因,您必须验证向您发送该证书的反向代理一种或另一种方式的信息)。

【讨论】:

    【解决方案3】:

    除非有双向 SSL 身份验证,否则不会有客户端证书。证书的存在就足够证明了。

    【讨论】:

    • 事实是我们要验证 两个 X.509 证书:一个由客户端发送,一个由代理使用。因此,一旦请求到达 WebLogic 服务器,在适当的请求中,将有这两个 X.509 证书:客户端在与反向代理的 SSL 会话中使用的证书(由反向代理作为 HTTP 标头发送),以及由反向代理用于反向代理和 WebLogic 服务器之间的 SSL 连接的一个(用于与 WebLogic 服务器的 SSL 握手)。这有意义吗?
    • @vor23 所以你必须查看证书才能知道它是什么。问题仍然没有意义。
    • 我们要验证客户端和反向代理之间的路径,以及反向代理和应用程序之间的路径,都通过双向 SSL 保护。当我打电话给HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") 时,我只得到一个证书链。我的问题本质上是这样的:我如何从 servlet 验证反向代理既向我发送 WL-Proxy-Client-Cert 标头 并且 通过双向 SSL 连接到我?
    • @vor23 反向代理和 servlet 之间的路径通常根本不安全,除非它是非 LAN 路径。您可以相信 Apache HTTPD 会正确地为您提供客户端证书。
    猜你喜欢
    • 1970-01-01
    • 2018-01-27
    • 2011-03-01
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 2019-12-29
    相关资源
    最近更新 更多