使用Apache CXF注释的UsernameToken WS-Security(WSS4J)

我正在尝试创建一个“java first”webservice,它将使用简单的UsernameToken WS-Security。 我试图遵循CXF的例子。 当我查询我的wsdl时,我看不到任何与安全相关的内容。 我正在使用CXF 2.7.5而我正在尝试用注释做所有事情。

以下是我失败的尝试:

SampleService.java:

import java.util.ArrayList; import java.util.Date; import javax.jws.WebParam; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import org.apache.cxf.annotations.EndpointProperties; import org.apache.cxf.annotations.EndpointProperty; @WebService(targetNamespace="https://test.company.com/ws/") @SOAPBinding(style = SOAPBinding.Style.RPC) @EndpointProperties({ @EndpointProperty(key = "action", value="UsernameToken"), @EndpointProperty(key = "passwordType", value="PasswordText"), @EndpointProperty(key = "ws-security.callback-handler", value="PasswordHandler"), //@EndpointProperty(key = "ws-security.validate.token", value="false"), }) public interface SampleService { @WebMethod public String getSample( @WebParam(name="startDate") Date startDate, @WebParam(name="endDate") Date endDate); } 

SampleServiceImpl.java:

 import java.util.Date; import javax.jws.WebMethod; import javax.jws.WebService; @WebService(endpointInterface = "SampleService", targetNamespace="https://test.company.com/ws/") public class SampleServiceImpl implements SampleService { @Override @WebMethod public String getSample(Date startDate, Date endDate) { StringBuilder sb = new StringBuilder(); sb.append("Start Date: "); sb.append(startDate.toString()); sb.append("\n"); sb.append("End Date: "); sb.append(endDate.toString()); return sb.toString(); } } 

PasswordHandler.java:

 import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback; public class PasswordHandler implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; System.out.println("User: " + pc.getIdentifier()); System.out.println("Password: " + pc.getIdentifier()); System.out.println("Type: " + pc.getType()); if (pc.getIdentifier().equals("joe")) { // set the password on the callback. This will be compared to the // password which was sent from the client. pc.setPassword("password"); } } } 

SampleServicePublisher.java:

 import java.util.HashMap; import java.util.Map; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.jaxws.EndpointImpl; import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import org.apache.ws.security.WSConstants; import org.apache.ws.security.handler.WSHandlerConstants; public class SampleServicePublisher { public static void main(String[] args) { String URL = "http://localhost:9999/ws/SampleService"; EndpointImpl jaxWsEndpoint = (EndpointImpl) javax.xml.ws.Endpoint.publish(URL, new SampleServiceImpl()); Endpoint cxfEndpoint = jaxWsEndpoint.getServer().getEndpoint(); Map inProps= new HashMap(); // how to configure the properties is outlined below; WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); cxfEndpoint.getInInterceptors().add(wssIn); Map outProps = new HashMap(); // how to configure the properties is outlined below; WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); cxfEndpoint.getOutInterceptors().add(wssOut); inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); // Password type : plain text inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); // for hashed password use: //properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); // Callback used to retrieve password for given user. inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName()); } } 

mvn依赖项:

   org.apache.cxf cxf-rt-frontend-jaxws 2.7.5   org.apache.cxf cxf-rt-transports-http 2.7.5    org.apache.cxf cxf-rt-transports-http-jetty 2.7.5   org.apache.cxf cxf-rt-ws-rm 2.7.5   org.apache.cxf cxf-rt-ws-security 2.7.5   org.apache.cxf cxf-rt-ws-addr 2.7.5   org.apache.cxf cxf-rt-ws-policy 2.7.5   

您可以使用基于WS-SecurityPolicy的配置而不是WSS4J拦截器方法!

为此,请从“java first”Web服务创建一个.wsdl文件,并使用和部分扩展它,并将其放在项目的任何位置。 (fe / WEB-INF / wsdl)

  ...   ....                                             

在@Webservice批注中定义wsdlLocation参数,并使用@EndpointConfig批注而不是@EndpointProperties。

 @Stateless @WebService ( portName = "SecurityServicePort", serviceName = "SecurityService", wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl", targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.wsdl.ServiceIface" ) @EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml", configName = "Custom WS-Security Endpoint") public class ServiceImpl implements ServiceIface { public String sayHello() { return helloservice.sayHello(); } } 

在WEB-INF / jaxws-endpoint-config.xml中定义ws-security.callback-handler。

    Custom WS-Security Endpoint  ws-security.callback-handler org.jboss.test.ws.jaxws.samples.wsse.policy.basic.UsernamePasswordCallback    

mvn依赖项:

   org.apache.cxf cxf-rt-ws-security ${cxf.version} provided   org.jboss.ws.native jbossws-native-core 4.1.1.Final provided  

加载org.apache.ws.security JBOSS模块:WEB-INF / jboss-depoyment-structure.xml:

         

我实现了helloworld projekt: https : //github.com/matyig/wsse-policy-username

如果您想使用非WS-SecurityPolicy方法,则可以使用spring xml配置方式。 你在这里找到一个很好的教程:

http://www.jroller.com/gmazza/entry/cxf_usernametoken_profile