2013-05-23 5 views
5

간단하고 간단한 UsernameToken WS-Security를 ​​사용하는 "java first"웹 서비스를 만들려고합니다. 나는 CXF의 사례를 따르려고 시도했다. 내 wsdl을 쿼리 할 때 ws-security와 관련된 언급이 없습니다. 저는 CXF 2.7.5를 사용하고 있으며 주석으로 모든 것을하려고합니다.UsernameToken WS-Security with Apache CXF Annotations (WSS4J)

는 IS 다음 내 시도가 실패한 :

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<String,Object> inProps= new HashMap<String,Object>(); 
     // how to configure the properties is outlined below; 

     WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); 
     cxfEndpoint.getInInterceptors().add(wssIn); 

     Map<String,Object> outProps = new HashMap<String,Object>(); 
     // 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 종속성 :

<dependencies> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-frontend-jaxws</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-transports-http</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <!-- Jetty is needed if you're using the CXFServlet --> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-transports-http-jetty</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-ws-rm</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-ws-security</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-ws-addr</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.cxf</groupId> 
     <artifactId>cxf-rt-ws-policy</artifactId> 
     <version>2.7.5</version> 
    </dependency> 
</dependencies> 

답변

2

대신 WSS4J 요격 방식의 WS-SecurityPolicy를 기반 구성을 사용할 수 있습니다!

이렇게하려면 "java first"웹 서비스에서 .wsdl 파일을 만들고 and로 부분을 확장하고 프로젝트의 아무 곳에 나 붙여 넣으십시오. (f.e./WEB-INF/WSDL)

 ... 
     <binding name="SecurityServicePortBinding" type="tns:ServiceIface"> 
     <wsp:PolicyReference URI="#SecurityServiceBindingPolicy"/> 
     .... 
     </binding>  
     <service name="SecurityService"> 
     <port name="SecurityServicePort" binding="tns:SecurityServicePortBinding"> 
      <soap:address location="https://localhost:8443/jaxws-samples-wsse-policy-username"/> 
     </port> 
     </service> 

    <wsp:Policy wsu:Id="SecurityServiceBindingPolicy"> 
     <wsp:ExactlyOne> 
      <wsp:All> 
       <wsaw:UsingAddressing 
       xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" 
       wsp:Optional="true" /> 
       <sp:TransportBinding> 
       <wsp:Policy> 
        <sp:TransportToken> 
         <wsp:Policy> 
          <sp:HttpsToken 
          RequireClientCertificate="false" /> 
         </wsp:Policy> 
        </sp:TransportToken> 
        <sp:Layout> 
         <wsp:Policy> 
          <sp:Lax /> 
         </wsp:Policy> 
        </sp:Layout> 
        <sp:IncludeTimestamp/> 
        <sp:AlgorithmSuite> 
         <wsp:Policy> 
          <sp:Basic128 /> 
         </wsp:Policy> 
        </sp:AlgorithmSuite> 
       </wsp:Policy> 
       </sp:TransportBinding> 
       <sp:SignedSupportingTokens> 
       <wsp:Policy> 
        <sp:UsernameToken 
         sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> 
         <wsp:Policy> 
          <sp:WssUsernameToken10 /> 
         </wsp:Policy> 
        </sp:UsernameToken> 
       </wsp:Policy> 
       </sp:SignedSupportingTokens> 
       <sp:Wss11 /> 
      </wsp:All> 
     </wsp:ExactlyOne> 
    </wsp:Policy>    
</definitions> 

은 @WebService 주석 내의 그러나 wsdlLocation 매개 변수를 정의하고 @EndpointProperties을 @EndpointConfig 주석을 사용하지 않음.

@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를 정의하십시오.

<?xml version="1.0" encoding="UTF-8"?> 

<jaxws-config xmlns="urn:jboss:jbossws-jaxws-config:4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="urn:jboss:jbossws-jaxws-config:4.0 schema/jbossws-jaxws-config_4_0.xsd"> 

    <endpoint-config> 
    <config-name>Custom WS-Security Endpoint</config-name> 
    <property> 
     <property-name>ws-security.callback-handler</property-name> 
     <property-value>org.jboss.test.ws.jaxws.samples.wsse.policy.basic.UsernamePasswordCallback</property-value> 
    </property> 
    </endpoint-config> 

</jaxws-config> 

MVN 의존성 :

<dependency> 
    <groupId>org.apache.cxf</groupId> 
    <artifactId>cxf-rt-ws-security</artifactId> 
    <version>${cxf.version}</version> 
    <scope>provided</scope> 
    </dependency>  
    <dependency> 
    <groupId>org.jboss.ws.native</groupId> 
    <artifactId>jbossws-native-core</artifactId> 
    <version>4.1.1.Final</version> 
    <scope>provided</scope> 
    </dependency> 

로드 org.apache.ws.security JBOSS 모듈 : WEB-INF/보스-depoyment-structure.xml :

<?xml version="1.0" encoding="UTF-8"?> 
<jboss-deployment-structure> 
    <deployment> 
     <dependencies> 
      <module name="org.apache.ws.security"/> 
     </dependencies> 
    </deployment> 
</jboss-deployment-structure> 

I helloworld 프로젝트 구현 : https://github.com/matyig/wsse-policy-username

Non-WS-SecurityPolicy 접근 방식을 사용하면 spring xml 구성 방법을 사용할 수 있습니다.

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

+1

클라이언트 측에서 패스 월드 호출 핸들러를 구현해야 할 이유가 한 가지를하지 않는 : 당신은 여기 좋은 자습서를 찾을 수 있습니다. 클라이언트는 걱정할 필요가 없습니다. 클라이언트가 PHP 또는 .NET 인 경우 어떻게 작동합니까 ??? – Makky