众所周知,WS-Security设定的目标之一是对SOAP消息强制执行完整性和/或保密。 在完整性的情况下,添加到SOAP消息的签名是数学过程的结果,该过程涉及发送者的私钥,从而导致加密的消息摘要。
默认情况下,大多数框架(例如WSS4J)仅对正文进行签名。 如果要添加额外的标头(例如Timestamp标头),则需要明确指示对其进行签名。 使用WSS4J例如Spring的支持,你可以设置包含本地元素名称的逗号分隔的列表,并使用securementSignatureParts属性对应的命名空间。
在下面的示例中,如何指示它对Body和Timestamp元素(及其同级元素)进行签名。 这将导致将两个数字签名附加到消息中:
<property name="securementSignatureParts" value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp">
</property>
最终,SOAP消息将与XML数字签名数据以及大多数情况下包含证书的BinarySecurityToken一起发送。 到目前为止没有新内容。 但是,令我吃惊的是,似乎没有广泛了解BST的目标是什么,也不知道如何使用它来控制身份验证。 让我尝试阐明一下:与SOAP消息一起发送的发件人的证书起着标识的作用。 您可以将其与用户名++进行比较。 应该清楚的是,消息中的证书不能被信任,用户名也不能不经过密码验证。 到目前为止,每个人都对此表示同意: “是的,当然,需要对证书进行验证才能被信任,然后您便会被设置!” 但这还不是全部。 证书的验证与身份验证不同。 消息中的证书有效并且由已知CA签名的事实不足以考虑发件人是否已通过身份验证。 例如:在最恶意的时刻,我本可以截取消息,更改内容,基于我的私钥创建新的签名并用我的证书替换消息中的BST。 我的证书完全可以是正式的CA签名证书(甚至由您使用的同一CA签名),因此它可以通过验证检查。 如果框架只是简单地验证消息中的证书,那么我们将完全没有安全性。
注意:如果您是通过安全传输发送邮件,则可能是我无法截获该邮件。 但是安全传输大多在实际端点之前终止,而使一小部分传输“不安全”。 尽管这部分将主要在公司内部进行,但是我想指出的是,无论您的传输多么安全,端点都有责任验证发件人的身份。 例如; 在异步系统中,SOAP消息可能已经放置在消息队列上,以便稍后进行处理。 当由端点开始处理时,安全传输的踪迹早已消失。 您必须使用消息中包含的信息来验证身份。
为了解决此漏洞,我们有两个解决方案:第一个解决方案进一步建立在我们已经描述的基础上:消息中的证书根据信任库中的CA根证书进行了验证。 在这种情况下,建议首先缩小可信CA的范围。 例如,您可以在有限的CA列表中与客户达成协议,以从中获取证书。 这样一来,您已经降低了信任更多“灰色区域” CA的风险,因为这些CA可能不遵循发出如此严格的证书的规则(例如,正确检查其客户的身份)。 其次,由于您的受信任CA发出的*每张*证书都将被视为“已认证”,因此我们将通过发出一些额外的支票来弥补漏洞。 使用WSS4J,可以基于证书的主题DN属性配置匹配模式。 他们对此有一个不错的博客条目: http : //coheigea.blogspot.ie/2012/08/subject-dn-certificate-constraint.html 。 我们可以指定证书的DN必须匹配给定值,如下所示:
Wss4jHandler handler = ...
handler.setOption(WSHandlerConstants.SIG_SUBJECT_CERT_CONSTRAINTS, "CN = ...");
注意:目前在Wss4jSecurityInterceptor中使用Spring对WSS4J的支持尚无此设置器,因此您必须对其进行扩展才能启用此功能!
总结正在执行的步骤:
- 消息中包含的证书已根据您的受托机构中的受信任CA进行了验证。 验证成功后,它将通知应用程序证书仍然有效,并且实际上已由您认为可信的CA分发了该证书。
- 此检查为我们保证了证书确实属于证书声称属于的一方。
- 您也可以选择在吊销时检查证书,以便我们不再继续信任被明确吊销的证书。
- WSS4J将检查证书的某些属性是否与特定服务的所需值匹配(主题DN证书约束支持)。
- 这将是身份验证步骤; 一旦发现证书有效,我们将检查证书的所有者是否也是我们要授予访问权限的证书的所有者
- 最后,通过创建消息的新摘要来验证消息中的签名,将其与消息中的解密摘要进行比较,依此类推。
请注意,默认情况下不进行此检查(至少在使用WSS4J时)! 如果您不指定它,而只是将您的CA添加到信任库中,您将留下一个安全漏洞!
第二种解决方案不需要额外的配置,并且仅取决于要在信任库中显示的发送者的证书。
消息中包含的证书与信任库中的证书匹配。 如果它们匹配,则对发送者进行身份验证。 无需针对CA验证证书,因为在信任库中导入的证书是显式可信的(WSS4J仍将检查证书是否未过期,并可能对其进行吊销检查)。 同样,信任库中没有CA证书(或CA中间证书)! 也只有您要授予访问权限的发件人的证书。 因此,通过从信任库中添加(或删除)其证书来控制访问。
这要求您在最初导入证书时要谨慎,因为您必须确保它们实际上代表发送者。 但这是在将证书添加到信任库时以及在添加CA证书(如第一个解决方案)时始终必须执行的操作。
结论
假设您可以限制受信任的CA,则在大多数情况下,第一种解决方案是首选的,也是最具扩展性的。 对于新客户端,不需要对信任库进行任何更改。 匹配的属性可以存储在外部,因此很容易更改/添加。 另外,当客户端证书过期或被吊销时,您无需执行任何特殊操作。 发件人将在给定时刻使用新证书,并将根据您的信任库中的CA直接对其进行验证。 在第二种解决方案中,您将必须将新证书添加到受托者中,并将旧证书保留一段时间,直到执行切换为止。
总体经验教训:水密安全很难。 IT领域的#1规则(假设是所有麻烦的源头)在这里确实是正确的。 持怀疑态度,并确保您完全了解正在发生的事情。 在您确定默认设置之前,请不要信任默认设置。 房子警报的默认设置(例如123456)也不是好主意。 Tomcat安装上的默认管理员密码也不是。
翻译自: https://www.javacodegeeks.com/2013/09/ws-security-using-binarysecuritytoken-for-authentication.html