我有一个场景,我几乎没有其余的 Web 服务,其中很少需要强制执行相互 ssl,而很少应该只有单向 ssl,这里是相同的 Web 应用程序。
这在基于 tomcat/Spring 的应用程序中可能吗?
抱歉回复晚了,是的,我这样做了,不确定是否是最好的方法,但有点黑客。
第 1 步: 在 Apache Tomcat 中使用
clientAuth=want
设置单向 SSL。
这将解决您希望所有 Web 服务使用一种 SSL 方式接受需要额外/相互身份验证的情况的情况。
第 2 步: 现在是需要双向 SSL 的 Web 服务。 编写一个 servlet 过滤器,并针对该特定 Web 服务 URL 检查传入的 http 请求中的证书。循环遍历请求中找到的证书并将其与您的信任存储中的证书进行匹配。如果您找到匹配项,则让请求流程继续进行,如果没有,则返回异常,因为找不到 SSL 证书。
X509Certificate[] certificates = (X509Certificate[]) request
.getAttribute("javax.servlet.request.X509Certificate");
上面的代码将为您提供请求中的证书数组。
注意:确保您的 SSL 配置正确,否则证书变量将保持为空。
如果你可以使用不同的主机(假设客户端和服务器支持SNI)或端口,那么这应该没有问题。
遗憾的是,您无法根据 URL 的路径更改 SSL 配置,因为它仅在建立 SSL 连接后才可用。在这种情况下,您唯一的选择是将客户端证书设置为可选,并忽略为不需要它的 URL 发送的任何证书。
无论哪种情况,几乎肯定让 Nginx 或 Apache httpd 之类的东西处理 SSL 部分并将有关客户端证书(或缺少证书)的任何数据传递到 HTTP 标头中的 Spring / Tomcat 应用程序会更好。
您可以对整个站点使用 TLS(“单向”),然后仅在需要身份验证时才需要客户端证书。将 TLS
<Connector>
的 clientAuth
属性设置为 want
,并将 auth-method
中的 web.xml
设置为 CLIENT-CERT
。应该可以了。