龙空技术网

Spring Boot 整合CXF实现数字证书签名功能

余山科技 133

前言:

此时咱们对“apachecxf文件”可能比较关心,咱们都需要知道一些“apachecxf文件”的相关文章。那么小编也在网摘上网罗了一些有关“apachecxf文件””的相关资讯,希望咱们能喜欢,各位老铁们一起来了解一下吧!

一、前言

上一篇已经完整的讲解了Spring Boot 整合CXF实现SSL会话的整个流程,在此基础上将继续讲解基于SSL会话的签名和验签功能实现。

项目源码:

spring-cxf参考源码:

spring-ws参考源码:

二、开发环境

IDE::IDEA

JDK:1.8

maven:3.6.2

spring boot:2.4.0

cxf:3.4.1

三、实现步骤

具体代码实现参考整合CXF添加日志拦截器样。本章在之前基础上讲解新增内容。

3.1、实现服务端和客户端

新建服务端和客户端spring-cxf-client-signature,spring-cxf-server-signature,并完成服务部署和客户端访问接口,具体步骤见上一篇。

3.2、添加security依赖

spring boot与cxf整合后要进行验签和加解密也只需引入cxf-rt-ws-security,并实现相关配置即可。

服务端、客服端pom文件中添加cxf依赖包

<dependency>   <groupId>org.apache.cxf</groupId>   <artifactId>cxf-rt-ws-security</artifactId>   <version>3.4.1</version></dependency>

3.3、服务端配置加解密及验签信息

在服务端配置类中定义入参和出参的加解密拦截器配置

package org.ouyushan.cxf.config;import org.apache.cxf.Bus;import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;import org.apache.cxf.ext.logging.LoggingInInterceptor;import org.apache.cxf.ext.logging.LoggingOutInterceptor;import org.apache.cxf.jaxws.EndpointImpl;import org.apache.cxf.transport.servlet.CXFServlet;import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;import org.apache.wss4j.dom.handler.WSHandlerConstants;import org.ouyushan.cxf.component.ServerPasswordCallback;import org.ouyushan.cxf.service.UserService;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.web.servlet.ServletRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;import javax.xml.ws.Endpoint;import java.util.HashMap;import java.util.Map;/** * @Description: 服务端配置类 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/12/03 14:38 */@Configurationpublic class CxfServerConfig {    @Value("${client.keyAlias}")    private String keyAlias;    @Value("${client.trustAlias}")    private String trustAlias;    @Resource    private Bus bus;    @Resource    private UserService userService;    @Bean    public ServletRegistrationBean cxfServlet() {        return new ServletRegistrationBean(new CXFServlet(), "/ws/*");    }    @Bean    public Endpoint userEndpoint() {        EndpointImpl endpoint = new EndpointImpl(bus, userService);        endpoint.publish("/user");        // log the request and response messages        endpoint.getInInterceptors().add(loggingInInterceptor());        endpoint.getOutInterceptors().add(loggingOutInterceptor());        // add the WSS4J IN interceptor to verify the signature on the response message        endpoint.getInInterceptors().add(serverWssIn());        // add the WSS4J OUT interceptor to sign the request message        endpoint.getOutInterceptors().add(serverWssOut());        return endpoint;    }    @Bean    public LoggingInInterceptor loggingInInterceptor() {        return new LoggingInInterceptor();    }    @Bean    public LoggingOutInterceptor loggingOutInterceptor() {        return new LoggingOutInterceptor();    }    /**     * 以下为服务REQ_IN、REQ_OUT的加解密和验签配置     *     * @return     */    @Bean    public Map<String, Object> serverInProps() {        Map<String, Object> serverInProps = new HashMap<>();        serverInProps.put(WSHandlerConstants.ACTION, /*WSHandlerConstants.TIMESTAMP + " " +*/ WSHandlerConstants.SIGNATURE);        serverInProps.put(WSHandlerConstants.SIGNATURE_USER, keyAlias);        serverInProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordCallback.class.getName());        // 验签        serverInProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_trust.properties");        return serverInProps;    }    @Bean    public Map<String, Object> serverOutProps() {        Map<String, Object> serverOutProps = new HashMap<>();        serverOutProps.put(WSHandlerConstants.ACTION, /*WSHandlerConstants.TIMESTAMP + " " +*/ WSHandlerConstants.SIGNATURE);        serverOutProps.put(WSHandlerConstants.SIGNATURE_USER, trustAlias);        serverOutProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordCallback.class.getName());        // 签名        serverOutProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_key.properties");        return serverOutProps;    }    @Bean    public WSS4JInInterceptor serverWssIn() {        WSS4JInInterceptor serverWssIn = new WSS4JInInterceptor();        serverWssIn.setProperties(serverInProps());        return serverWssIn;    }    @Bean    public WSS4JOutInterceptor serverWssOut() {        WSS4JOutInterceptor serverWssOut = new WSS4JOutInterceptor();        serverWssOut.setProperties(serverOutProps());        return serverWssOut;    }}

加解密及验签拦截器属性信息配置

server_key.properties

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlinorg.apache.wss4j.crypto.merlin.keystore.type=PKCS12org.apache.wss4j.crypto.merlin.keystore.private.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.alias=webserverorg.apache.wss4j.crypto.merlin.keystore.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.file=jks/webserver.p12

server_trust.properties

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlinorg.apache.wss4j.crypto.merlin.keystore.type=PKCS12org.apache.wss4j.crypto.merlin.keystore.private.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.alias=webclientorg.apache.wss4j.crypto.merlin.keystore.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.file=jks/webclient.p12

密码回调方法实现类ServerPasswordCallback:

package org.ouyushan.cxf.component;import org.apache.wss4j.common.ext.WSPasswordCallback;import org.springframework.stereotype.Component;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;/** * @Description: 设置回调密码 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/12/03 16:03 */@Componentpublic class ServerPasswordCallback implements CallbackHandler {    /**     * 自定义实现业务逻辑     *     * @param callbacks     */    @Override    public void handle(Callback[] callbacks) {        WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];        callback.setPassword("ouyushan.pass");    }}
3.4、客户端配置加解密及验签信息

CxfClientConfig.java

在服务端配置类中定义入参和出参的加解密拦截器配置

package org.ouyushan.cxf.config;import org.apache.cxf.ext.logging.LoggingInInterceptor;import org.apache.cxf.ext.logging.LoggingOutInterceptor;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;import org.apache.wss4j.dom.handler.WSHandlerConstants;import org.ouyushan.cxf.component.ClientPasswordCallback;import org.ouyushan.cxf.ws.UserService;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.HashMap;import java.util.Map;/** * @Description: * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/11/26 16:52 */@Configurationpublic class CxfClientConfig {    @Value("${client.keyAlias}")    private String keyAlias;    @Value("${client.trustAlias}")    private String trustAlias;    @Value("${server.serviceUrl}")    private String serviceUrl;    @Bean    public UserService userService() {        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();        jaxWsProxyFactoryBean.setServiceClass(UserService.class);        jaxWsProxyFactoryBean.setAddress(serviceUrl);        // log the request and response messages        jaxWsProxyFactoryBean.getInInterceptors().add(loggingInInterceptor());        jaxWsProxyFactoryBean.getOutInterceptors().add(loggingOutInterceptor());        // add the WSS4J OUT interceptor to sign the request message        jaxWsProxyFactoryBean.getOutInterceptors().add(clientWssOut());        //jaxWsProxyFactoryBean.getOutInterceptors().add(new SAAJOutInterceptor());        // add the WSS4J IN interceptor to verify the signature on the response message        jaxWsProxyFactoryBean.getInInterceptors().add(clientWssIn());        //jaxWsProxyFactoryBean.getInInterceptors().add(new SAAJInInterceptor());        UserService userService = (UserService) jaxWsProxyFactoryBean.create();        return userService;    }    @Bean    public LoggingInInterceptor loggingInInterceptor() {        return new LoggingInInterceptor();    }    @Bean    public LoggingOutInterceptor loggingOutInterceptor() {        return new LoggingOutInterceptor();    }    @Bean    public Map<String, Object> clientOutProps() {        Map<String, Object> clientOutProps = new HashMap<>();        clientOutProps.put(WSHandlerConstants.ACTION, /*WSHandlerConstants.TIMESTAMP + " " +*/ WSHandlerConstants.SIGNATURE);        clientOutProps.put(WSHandlerConstants.SIGNATURE_USER, keyAlias);        clientOutProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());        // 签名        clientOutProps.put(WSHandlerConstants.SIG_PROP_FILE, "client_key.properties");        return clientOutProps;    }    @Bean    public WSS4JOutInterceptor clientWssOut() {        WSS4JOutInterceptor clientWssOut = new WSS4JOutInterceptor();        clientWssOut.setProperties(clientOutProps());        return clientWssOut;    }    @Bean    public Map<String, Object> clientInProps() {        Map<String, Object> clientInProps = new HashMap<>();        clientInProps.put(WSHandlerConstants.ACTION, /*WSHandlerConstants.TIMESTAMP + " " +*/ WSHandlerConstants.SIGNATURE);        clientInProps.put(WSHandlerConstants.SIGNATURE_USER, trustAlias);        clientInProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());        // 验签        clientInProps.put(WSHandlerConstants.SIG_PROP_FILE, "client_trust.properties");        return clientInProps;    }    @Bean    public WSS4JOutInterceptor clientWssIn() {        WSS4JOutInterceptor clientWssIn = new WSS4JOutInterceptor();        clientWssIn.setProperties(clientInProps());        return clientWssIn;    }}

加解密及验签拦截器属性信息配置

client_trust.properties

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlinorg.apache.wss4j.crypto.merlin.keystore.type=PKCS12org.apache.wss4j.crypto.merlin.keystore.private.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.alias=webserverorg.apache.wss4j.crypto.merlin.keystore.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.file=jks/webserver.p12

client_key.properties

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlinorg.apache.wss4j.crypto.merlin.keystore.type=PKCS12org.apache.wss4j.crypto.merlin.keystore.private.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.alias=webclientorg.apache.wss4j.crypto.merlin.keystore.password=ouyushan.passorg.apache.wss4j.crypto.merlin.keystore.file=jks/webclient.p12

密码回调方法实现类ClientPasswordCallback:

package org.ouyushan.cxf.component;import org.apache.wss4j.common.ext.WSPasswordCallback;import org.springframework.stereotype.Component;import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;/** * @Description: 设置回调密码 * @Author: ouyushan * @Email: ouyushan@hotmail.com * @Date: 2020/12/03 16:03 */@Componentpublic class ClientPasswordCallback implements CallbackHandler {    /**     * 自定义实现业务逻辑     *     * @param callbacks     */    @Override    public void handle(Callback[] callbacks) {        WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];        callback.setPassword("ouyushan.pass");    }}

application.yml

server:  port: 7070  serviceUrl: :  keyAlias: webclient  trustAlias: webserver
3.4、功能验证

分别启动服务端和客户端,访问客户端请求接口:

客户端控制台输出如下:

2020-12-08 13:46:36.813  INFO 1928 --- [nio-7070-exec-1] o.a.cxf.services.UserService.REQ_OUT     : REQ_OUT    Address:     HttpMethod: POST    Content-Type: text/xml    ExchangeId: 61972ff8-df54-45f9-af4a-f5fc5b338156    ServiceName: UserServiceService    PortName: UserServicePort    PortTypeName: UserService    Headers: {SOAPAction="", Accept=*/*}    Payload: <soap:Envelope xmlns:soap=";><soap:Header><wsse:Security xmlns:wsse="; xmlns:wsu="; soap:mustUnderstand="1"><ds:Signature xmlns:ds="; Id="SIG-8d966868-dd6e-4802-a301-eb2232357ab3"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=";><ec:InclusiveNamespaces xmlns:ec="; PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=";/><ds:Reference URI="#id-dbf085d0-453d-42b8-8c45-e011704fb15c"><ds:Transforms><ds:Transform Algorithm=";/></ds:Transforms><ds:DigestMethod Algorithm=";/><ds:DigestValue>7YUMFs3792vDX3W2fTtWXzejCMI=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>OYYq87+D7mF7NIo05CVpP0+K7bpHWgRhDU5YkstkvmUOJXctY/yt0+jgPJ9u6hIIddwN45nAuFTcV1sGqyc403D1WyZYVyW3M0jK53VTLDGIex++D2rTh+g/stYd05QTfaQlrBUz5PiZoQOCm53zhnAdt2j+5UaRQMPC1aqeSCSZWjkunbDqYwRyY2opHBPVNC2J+3SYaEN9mP8AxJP7mTlGqUAR53SFKoTvwOkbaRtwJ4TJXt6oBO7VV1SgCrRVgiWcBzOtaPLFnqKWutjWYz1CSdW3hvWDZu36NB9k3nuph4G27HHOb0AKQnDG8vUDGg+essChtXBhmPgc+9tO1Q==</ds:SignatureValue><ds:KeyInfo Id="KI-dff1133f-e849-4163-9a09-955606f35c15"><wsse:SecurityTokenReference xmlns:wsse="; xmlns:wsu="; wsu:Id="STR-ec4117ae-cb91-4228-b346-3846cd5926c6"><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=webclient,OU=ouyushan,O=ouyushan,L=beijing,ST=beijing,C=CN</ds:X509IssuerName><ds:X509SerialNumber>1417430396</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soap:Header><soap:Body xmlns:wsu="; wsu:Id="id-dbf085d0-453d-42b8-8c45-e011704fb15c"><ns2:getUserName xmlns:ns2=";><userId>1</userId></ns2:getUserName></soap:Body></soap:Envelope>2020-12-08 13:46:39.088  WARN 1928 --- [nio-7070-exec-1] o.a.cxf.phase.PhaseInterceptorChain      : Skipping interceptor org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor: Phase pre-protocol-ending specified does not exist.2020-12-08 13:46:39.342  INFO 1928 --- [nio-7070-exec-1] o.a.cxf.services.UserService.RESP_IN     : RESP_IN    Address:     Content-Type: text/xml;charset=UTF-8    ResponseCode: 200    ExchangeId: 61972ff8-df54-45f9-af4a-f5fc5b338156    ServiceName: UserServiceService    PortName: UserServicePort    PortTypeName: UserService    Headers: {Keep-Alive=timeout=60, connection=keep-alive, content-type=text/xml;charset=UTF-8, Content-Length=2343, Date=Tue, 08 Dec 2020 05:46:39 GMT}    Payload: <soap:Envelope xmlns:soap=";><soap:Header><wsse:Security xmlns:wsse="; xmlns:wsu="; soap:mustUnderstand="1"><ds:Signature xmlns:ds="; Id="SIG-d20e91d6-895b-4813-ae50-461b487895f6"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=";><ec:InclusiveNamespaces xmlns:ec="; PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=";/><ds:Reference URI="#id-78245bbb-fd1b-4b76-b878-5fdcf02bbcb6"><ds:Transforms><ds:Transform Algorithm=";/></ds:Transforms><ds:DigestMethod Algorithm=";/><ds:DigestValue>H3Gcn4FEcctHT4b7BRlUTLjSs44=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>GXaBUSoZPTxsoVWMwd5oXBhYr8LSGCG3R3TgxPWIRnz4kqLUyR47X/l+iAATLJPa4GoLPZeTzGxChcx9F024/HuVZLU9mQ2KNIQqgkfssbOd7kv71/9wrROK4mdefx8sMsNHC9Z8E/DEpNgBlJJE4UpeBxBvfqI/6ESoi+xys/0CUSqP5WtOSOeG/DbwR+Q8jMIvdAYFArZ9wDk0RIGLaROYSfSu7J3oSeu9gtmRF4O5UazWzktnotVacqlSPMKmz6A9QeAsRd163oNv6EquCOxcp5uPVWr/CNyv/j4ghgYUEH7C2fkUv5UZRYBBK7mRP/m4PHt4tAVgmH9PBKT5Sg==</ds:SignatureValue><ds:KeyInfo Id="KI-c4a46360-fa25-43d8-a617-6f5161cace57"><wsse:SecurityTokenReference xmlns:wsse="; xmlns:wsu="; wsu:Id="STR-40489c37-23fa-4691-b509-d71751d7dedb"><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=webserver,OU=ouyushan,O=ouyushan,L=beijing,ST=beijing,C=CN</ds:X509IssuerName><ds:X509SerialNumber>905289312</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soap:Header><soap:Body xmlns:wsu="; wsu:Id="id-78245bbb-fd1b-4b76-b878-5fdcf02bbcb6"><ns2:getUserNameResponse xmlns:ns2=";><return>tom</return></ns2:getUserNameResponse></soap:Body></soap:Envelope>

服务端控制台输出如下:

2020-12-08 13:46:38.649  INFO 6812 --- [nio-8080-exec-1] o.a.cxf.services.UserService.REQ_IN      : REQ_IN    Address:     HttpMethod: POST    Content-Type: text/xml; charset=UTF-8    ExchangeId: f6631eb5-a99b-4481-ae32-9aac6b603813    ServiceName: UserService    PortName: UserServiceImplPort    PortTypeName: UserService    Headers: {SOAPAction="", Accept=*/*, host=localhost:8080, connection=keep-alive, content-type=text/xml; charset=UTF-8, cache-control=no-cache, Content-Length=2326, pragma=no-cache, user-agent=Apache-CXF/3.4.1}    Payload: <soap:Envelope xmlns:soap=";><soap:Header><wsse:Security xmlns:wsse="; xmlns:wsu="; soap:mustUnderstand="1"><ds:Signature xmlns:ds="; Id="SIG-8d966868-dd6e-4802-a301-eb2232357ab3"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=";><ec:InclusiveNamespaces xmlns:ec="; PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=";/><ds:Reference URI="#id-dbf085d0-453d-42b8-8c45-e011704fb15c"><ds:Transforms><ds:Transform Algorithm=";/></ds:Transforms><ds:DigestMethod Algorithm=";/><ds:DigestValue>7YUMFs3792vDX3W2fTtWXzejCMI=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>OYYq87+D7mF7NIo05CVpP0+K7bpHWgRhDU5YkstkvmUOJXctY/yt0+jgPJ9u6hIIddwN45nAuFTcV1sGqyc403D1WyZYVyW3M0jK53VTLDGIex++D2rTh+g/stYd05QTfaQlrBUz5PiZoQOCm53zhnAdt2j+5UaRQMPC1aqeSCSZWjkunbDqYwRyY2opHBPVNC2J+3SYaEN9mP8AxJP7mTlGqUAR53SFKoTvwOkbaRtwJ4TJXt6oBO7VV1SgCrRVgiWcBzOtaPLFnqKWutjWYz1CSdW3hvWDZu36NB9k3nuph4G27HHOb0AKQnDG8vUDGg+essChtXBhmPgc+9tO1Q==</ds:SignatureValue><ds:KeyInfo Id="KI-dff1133f-e849-4163-9a09-955606f35c15"><wsse:SecurityTokenReference xmlns:wsse="; xmlns:wsu="; wsu:Id="STR-ec4117ae-cb91-4228-b346-3846cd5926c6"><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=webclient,OU=ouyushan,O=ouyushan,L=beijing,ST=beijing,C=CN</ds:X509IssuerName><ds:X509SerialNumber>1417430396</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soap:Header><soap:Body xmlns:wsu="; wsu:Id="id-dbf085d0-453d-42b8-8c45-e011704fb15c"><ns2:getUserName xmlns:ns2=";><userId>1</userId></ns2:getUserName></soap:Body></soap:Envelope>2020-12-08 13:46:39.032  INFO 6812 --- [nio-8080-exec-1] o.a.cxf.services.UserService.RESP_OUT    : RESP_OUT    Address:     Content-Type: text/xml    ResponseCode: 200    ExchangeId: f6631eb5-a99b-4481-ae32-9aac6b603813    ServiceName: UserService    PortName: UserServiceImplPort    PortTypeName: UserService    Headers: {}    Payload: <soap:Envelope xmlns:soap=";><soap:Header><wsse:Security xmlns:wsse="; xmlns:wsu="; soap:mustUnderstand="1"><ds:Signature xmlns:ds="; Id="SIG-d20e91d6-895b-4813-ae50-461b487895f6"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm=";><ec:InclusiveNamespaces xmlns:ec="; PrefixList="soap"/></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=";/><ds:Reference URI="#id-78245bbb-fd1b-4b76-b878-5fdcf02bbcb6"><ds:Transforms><ds:Transform Algorithm=";/></ds:Transforms><ds:DigestMethod Algorithm=";/><ds:DigestValue>H3Gcn4FEcctHT4b7BRlUTLjSs44=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>GXaBUSoZPTxsoVWMwd5oXBhYr8LSGCG3R3TgxPWIRnz4kqLUyR47X/l+iAATLJPa4GoLPZeTzGxChcx9F024/HuVZLU9mQ2KNIQqgkfssbOd7kv71/9wrROK4mdefx8sMsNHC9Z8E/DEpNgBlJJE4UpeBxBvfqI/6ESoi+xys/0CUSqP5WtOSOeG/DbwR+Q8jMIvdAYFArZ9wDk0RIGLaROYSfSu7J3oSeu9gtmRF4O5UazWzktnotVacqlSPMKmz6A9QeAsRd163oNv6EquCOxcp5uPVWr/CNyv/j4ghgYUEH7C2fkUv5UZRYBBK7mRP/m4PHt4tAVgmH9PBKT5Sg==</ds:SignatureValue><ds:KeyInfo Id="KI-c4a46360-fa25-43d8-a617-6f5161cace57"><wsse:SecurityTokenReference xmlns:wsse="; xmlns:wsu="; wsu:Id="STR-40489c37-23fa-4691-b509-d71751d7dedb"><ds:X509Data><ds:X509IssuerSerial><ds:X509IssuerName>CN=webserver,OU=ouyushan,O=ouyushan,L=beijing,ST=beijing,C=CN</ds:X509IssuerName><ds:X509SerialNumber>905289312</ds:X509SerialNumber></ds:X509IssuerSerial></ds:X509Data></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></soap:Header><soap:Body xmlns:wsu="; wsu:Id="id-78245bbb-fd1b-4b76-b878-5fdcf02bbcb6"><ns2:getUserNameResponse xmlns:ns2=";><return>tom</return></ns2:getUserNameResponse></soap:Body></soap:Envelope>

从日志可以看出完整的请求链路信息,在客户端REQ_OUT和服务端的REQ_IN的Payload中已包含Signature签名信息,说明签名已经生效。

四、总结

通过本篇教材,您应该已掌握Spring Boot整合CXF实现数字证书签名功能。整个过程可分为三步:

准备相应证书;服务端数字证书签名拦截器;客户端数字证书签名拦截器。

至此Spring Boot 整合CXF实现数字签名已完成,在测试过程中可能会出现用户名为空,证书无法加载等问题,请确保证书信息正确,并配置无误。

标签: #apachecxf文件