我可以为每个 servlet 使用不同的 SSL 证书吗?

Posted

技术标签:

【中文标题】我可以为每个 servlet 使用不同的 SSL 证书吗?【英文标题】:Can I have different SSL certificate for each servlet? 【发布时间】:2014-08-23 14:52:41 【问题描述】:

这是我的 GWT Web 应用程序中 web.xml 配置的 sn-p

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

      <web-app>

      <servlet>
       <servlet-name>firstServlet</servlet-name>
       <servlet-class>com.test.server.First</servlet-class>
      </servlet>


      <servlet>
       <servlet-name>secondServlet</servlet-name>
       <servlet-class>com.test.server.Second</servlet-class>
      </servlet>


      <servlet>
       <servlet-name>thirdServlet</servlet-name>
       <servlet-class>com.test.server.Third</servlet-class>
      </servlet>

    </web-app>

比方说:

firstServlet 是来自浏览器的每个查询的入口点 secondServlet 是来自 android 应用的每个查询的入口点 thirdServlet 是来自 ios 应用的每个查询的入口点

问题:

1 - 我可以为 secondServlet 和 thirdServlet 使用不同的 SSL 证书(可能是自签名的)而不影响 firstServlet 吗? (这意味着 firstServlet 将接受 http 查询,secondServlet 和 thirdServlet 将只接受 httpS 查询)。

2 - 我该怎么做? (web.xml 等相关 Servlet 所需的语法...)

谢谢,

【问题讨论】:

我不认为你可以;证书用于授权整个主机,而不仅仅是一个应用程序 这个问题似乎离题了,因为它与编程无关。请参阅帮助中心的What topics can I ask about here。也许Server Fault、Webmaster Stack Exchange 或Web Apps Stack Exchange 会是一个更好的提问地点。 @kolossus - 有一些标准可以验证服务器及其服务,而不仅仅是服务器。例如,参见RFC 6125, Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)。不过,我不知道 Apache 或 nginx 是否公开了它。这要问服务器管理员或网站管理员。 【参考方案1】:

实现这一目标的一种方法是结合应用程序和 Web 服务器配置。使用 Apache2 作为带有模块 mod_rewrite 的 web-front,您可以配置此重定向。然后,在您的应用程序中,您需要让每个 Servlet 在不同的 URL 中应答(映射)。

按照下面的例子,在第一个块中,HTTP 80 端口是 re:

在 apache 中,在 conf.d 目录中创建一个新的 conf 文件,如下例所示:

<VirtualHost 10.0.0.199:80>
    (...)
    #redirect all to https
    RewriteEngine on
    RewriteCond %HTTP_HOST   !^www\.yourdomain\.com [NC]
    RewriteCond %HTTP_HOST   !^$
    RewriteRule ^/(.*)         https://www.yourdomain.com/$1 [L,R]
    (...)
    #redirect based on URI to https
    RewriteCond %REQUEST_URI !^\/servlet1\/
    RewriteRule (.*) https://%HTTP_HOST$1 [L,R=301]
    (...)
</VirtualHost>

<VirtualHost 10.0.0.199:443>
    (...)
    RewriteEngine on
    RewriteCond %HTTP_HOST   !^www\.yourdomain\.com [NC]
    RewriteCond %HTTP_HOST   !^$
    RewriteRule ^/(.*)         https://www.yourdomain.com/$1 [L,R]
    (...)
</VirtualHost>

看看http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

【讨论】:

非常正确,但您不需要重写或重定向,只需 mod_proxy 或 mod_proxy_ajp。 感谢您的回答@mchamati。不过,您是否有一个简短的实际示例来描述您的概念?这个解释对我来说似乎有点太技术性了。先感谢您。问候 所有这些重写/反向代理都发生在证书发送之后。如果您想重定向到不同的服务器,这很好,但如果您想事先选择证书,则不行。【参考方案2】:

传统上,一个 IP 上只有一个证书。因此,如果您可以让您的 Web 服务器在其自己的 IP 地址(这也意味着另一个主机名)上处理每个 servlet,您就可以做到。示例:您在 servlet1.example.com 有一个服务器,在 servlet2.example.com 有另一个服务器,并且两台服务器都有不同的 IP 地址,那么您可以在每台服务器上使用具有不同证书的不同 servlet,或者您也可以拥有一台没有证书的服务器。

使用服务器名称指示,同一 IP 地址上可以有多个主机名,每个主机名可以有自己的证书。但是,不可能有任何没有证书的主机名,因为它们的 Web 服务器将在相同的 IP/端口上侦听 SSL 连接,并且只有在它从客户端获得初始 Hello 后才决定将提供哪个证书。因此,如果您只有几个 IP 地址,但每个 servlet 可以有一个唯一的主机名,那么您可以使用 SNI 来实现。但是任何应该没有证书的 servlet 都需要从与 https servlet 不同的 IP 地址提供服务。示例:如果您有 servlet1.example.com 和 servlet2.example.com 共享相同的 IP 地址,那么如果客户端支持 SNI(所有最近的浏览器都支持,但 IE8 不支持),那么您可以为每个服务器使用不同的证书)。但是你不能让 servlet1.example.com 成为 SSL,而 servlet2.example.com 不能,只要它们共享相同的 IP 地址。

不可能有特定于 URL 路径的证书,因为路径只有在 SSL 握手之后才知道,例如在已经提供证书之后。示例:https://www.example.com/servlet1https://www.example.com/servlet2 无法使用不同的证书,因为它们共享相同的主机名并且仅在 URL 的路径上有所不同。

【讨论】:

确实有可能。如果服务器想要根据路径发送不同的证书,则可以启动重新握手。 @EJP,原则上是这样,但所有这些不同的证书肯定需要对最初请求的相同主机名有效(这似乎有点毫无意义)。 感谢您的回答@Steffen。不过,您是否有一个简短的实际示例来描述您的概念?这个解释对我来说似乎有点太技术性了。先感谢您。问候, @user3793589:我希望我刚刚添加的示例有助于更好地理解问题。 @EJP:虽然可以通过重新协商来更改证书,但我知道没有服务器支持根据 URL 的路径重新协商到新证书。我也不确定客户是否会接受与原始请求不匹配的证书更改。你有更多关于这方面的信息吗?

以上是关于我可以为每个 servlet 使用不同的 SSL 证书吗?的主要内容,如果未能解决你的问题,请参考以下文章

AWS RDS SSL - 每个 RDS 实例的 ssl 服务器证书是不是不同或相同?

如何让 nginx 为多个虚拟主机做 SSL 透传?

在每个请求的.net HttpWebRequest上设置SecurityProtocol(Ssl3或TLS)

Nginx 中每个服务器的不同 TLS 协议

忽略 Servlet 中的 SSL 证书

使用和不使用 SSL 的 Apache 反向代理之间行为不同的原因