前面曾提到过这个问题:
http://blog.csdn.net/kunshan_shenbin/archive/2009/02/23/3928844.aspx
代码部分请先参考以前的博文:
http://blog.csdn.net/kunshan_shenbin/archive/2009/02/10/3872902.aspx
服务端WS-Security的配置如下:
Action使用Timestamp Encrypt Signature组合。
public class CXFNonSpringServletImpl extends CXFNonSpringServlet { private static final String SERVICE_SUFFIX = "";//"Facade"; private static final long serialVersionUID = 8262880864551976903L; @Override public void loadBus(ServletConfig servletConfig) throws ServletException { super.loadBus(servletConfig); Bus bus = getBus(); BusFactory.setDefaultBus(bus); registerPort("LoginUserService"); registerPort("LoginHstService"); } private S2Container getS2Container() { return SingletonS2ContainerFactory.getContainer(); } private void registerPort(String portName) { EndpointImpl jaxWsEndpoint = (EndpointImpl) EndpointImpl.publish("/" + StringUtils.capitalize(portName), getS2Container().getComponent(portName + SERVICE_SUFFIX)); Endpoint cxfEndPoint = (Endpoint) jaxWsEndpoint.getServer().getEndpoint(); cxfEndPoint.getInInterceptors().add(getKeystoreInInterceptor()); cxfEndPoint.getInInterceptors().add(new CXFLoggingInInterceptor()); cxfEndPoint.getOutInterceptors().add(getKeystoreOutInterceptor()); cxfEndPoint.getOutInterceptors().add(new CXFLoggingOutInterceptor()); } private WSS4JInInterceptor getKeystoreInInterceptor() { Map<String, Object> inProps = new HashMap<String, Object>(); inProps.put(WSHandlerConstants.ACTION, "Timestamp Encrypt Signature"); inProps.put(WSHandlerConstants.DEC_PROP_FILE, "server_insecurity_enc.properties"); inProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_insecurity_sign.properties"); inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName()); return new WSS4JInInterceptor(inProps); } private WSS4JOutInterceptor getKeystoreOutInterceptor() { Map<String, Object> outProps = new HashMap<String, Object>(); outProps.put(WSHandlerConstants.ACTION, "Timestamp Encrypt Signature"); outProps.put(WSHandlerConstants.USER, "apmserver"); outProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_insecurity_sign.properties"); outProps.put(WSHandlerConstants.ENC_PROP_FILE, "server_insecurity_enc.properties"); outProps.put(WSHandlerConstants.ENCRYPTION_USER, "apmclient"); outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference"); outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class.getName()); outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body"); outProps.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp"); outProps.put(WSHandlerConstants.ENC_SYM_ALGO, WSConstants.TRIPLE_DES); return new WSS4JOutInterceptor(outProps); } }
客户端配置如下(部分代码):
protected static WSS4JInInterceptor getKeystoreInInterceptor() { Map<String, Object> inProps = new HashMap<String, Object>(); inProps.put(WSHandlerConstants.ACTION, "Timestamp Encrypt Signature"); inProps.put(WSHandlerConstants.USER, "apmclient"); inProps.put(WSHandlerConstants.DEC_PROP_FILE, "server_insecurity_enc.properties"); inProps.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true"); inProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_insecurity_sign.properties"); inProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference"); inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientKeystorePasswordHandler.class.getName()); return new WSS4JInInterceptor(inProps); } protected static WSS4JOutInterceptor getKeystoreOutInterceptor() { Map<String, Object> outProps = new HashMap<String, Object>(); outProps.put(WSHandlerConstants.ACTION, "Timestamp Encrypt Signature"); outProps.put(WSHandlerConstants.USER, "apmclient"); outProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_insecurity_sign.properties"); outProps.put(WSHandlerConstants.DEC_PROP_FILE, "server_insecurity_enc.properties"); outProps.put(WSHandlerConstants.ENCRYPTION_USER, "apmserver"); outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference"); outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientKeystorePasswordHandler.class.getName()); outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body"); outProps.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp"); outProps.put(WSHandlerConstants.ENC_SYM_ALGO, "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); return new WSS4JOutInterceptor(outProps); } protected static void addInterceptor(Object client) { Client cxfClient = ClientProxy.getClient(client); Endpoint cxfEndpoint = cxfClient.getEndpoint(); cxfEndpoint.getInInterceptors().add(getKeystoreInInterceptor()); cxfEndpoint.getInInterceptors().add(new CXFLoggingInInterceptor()); cxfEndpoint.getOutInterceptors().add(getKeystoreOutInterceptor()); cxfEndpoint.getOutInterceptors().add(new CXFLoggingOutInterceptor()); }
如果采用上面这样的配置形式,当传输的数据中字符窜包含回车符,加密就会失败(可以通过Log反映出来)。
解决的办法是把服务端的如下2行代码删除:
outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body");
outProps.put(WSHandlerConstants.ENCRYPTION_PARTS, "{Content}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
当然,在客户端也存在对应的2行代码,统一起见也一起删除(事实上不删除也并不影响)。