我想在 SOAP 通信中从客户端证书中检索公用名(CN) 属性。我正在使用 Spring WebServiceTemplate创建我的 web 服务端点。我已经按照示例实现了 WS 相互认证。
是否有任何解决方案可以通过 WebServiceTemplate 或其他库从客户端请求中获取证书详细信息?
我想在 SOAP 通信中从客户端证书中检索公用名(CN) 属性。我正在使用 Spring WebServiceTemplate创建我的 web 服务端点。我已经按照示例实现了 WS 相互认证。
是否有任何解决方案可以通过 WebServiceTemplate 或其他库从客户端请求中获取证书详细信息?
幸运的是,我已经设法弄清楚了!Spring WS 提供了非常方便的方法来检索 X509Certificate。
通常,您有这样的端点:
@Endpoint
public class CountryEndpoint {
private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service";
...
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
@ResponsePayload
public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
//method body here
return response;
}
}
但是,Spring 允许在方法中添加附加参数,注释为@PayloadRoot。它可以是MessageContext实例。
public GetCountryResponse getCountry(@RequestPayload MessageContext context, @RequestPayload GetCountryRequest request)`
然后您将能够获取wsse:Security
标题,如下所示:
WebServiceMessage webServiceMessageRequest = context.getRequest();
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) webServiceMessageRequest;
SOAPMessage doc = saajSoapMessage.getSaajMessage();
Element elem = WSSecurityUtil.getSecurityHeader(doc.getSOAPPart(), "");
现在获取BinarySecurityToken
标签的正确内容:
String binarySecurityToken = elem.getElementsByTagName("BinarySecurityToken").item(0).getTextContent();
最后,您应该通过传递 binarySecurityToken 作为其构造函数参数来重新创建 X509Certificate。稍后您可以通过许多不同的方式提取 CN,例如通过 LDAP utlis。
还有另一种方法。
private final static QName SECURITY_QNAME = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "");
private static CertificateFactory certFactory;
public xxx() throws CertificateException {
super(Phase.PRE_PROTOCOL);
certFactory = CertificateFactory.getInstance("X.509");
}
@SneakyThrows
@Override
public void handleMessage(SoapMessage message) throws Fault {
SoapHeader header = (SoapHeader) message.getHeader(SECURITY_QNAME);
Node binarySignatureTag = ((Element) header.getObject()).getFirstChild();
BinarySecurity token = new X509Security((Element) binarySignatureTag, new BSPEnforcer());
InputStream in = new ByteArrayInputStream(token.getToken());
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);
}
@Bean
public Endpoint endpoint() throws CertificateException {
EndpointImpl endpoint = new EndpointImpl(springBus(), xxxPortType());
endpoint.setServiceName(xxxService().getServiceName());
endpoint.publish("/xxxx");
endpoint.getInInterceptors().add(new xxx());
return endpoint;
}