2010-02-24 4 views
27

일부 웹 서비스를 사용하기 위해 독립 실행 형 클라이언트를 만들려고합니다. 내 사용자 이름과 암호를 SOAP 헤더에 추가해야합니다.JAX-WS - SOAP 헤더 추가

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required. 

내가 잘못 뭐하는 거지 :

OTSWebSvcsService service = new OTSWebSvcsService(); 
OTSWebSvcs port = service.getOTSWebSvcs(); 

BindingProvider prov = (BindingProvider)port; 
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername"); 
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword"); 

... 

나는 다음과 같은 예외가 서비스의 메서드를 호출 할 때 다음과 같이 나는 자격 증명을 추가하는 시도? SOAP 머리글에 이러한 속성을 어떻게 추가합니까?

편집 : JDK6에 포함 된 JAX-WS 2.1을 사용하고있었습니다. 현재 JAX-WS 2.2를 사용 중입니다. 이제 다음 예외가 발생합니다.

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5509E: A security token whose type is [http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken] is required. 

이 토큰을 만드는 방법은 무엇입니까?

+0

에 사용자 이름과 암호를 추가 할 수 있습니다 참조? –

+0

JAX-WS 2.1은 JDK6에 포함되어 있습니다. –

답변

25

100 %는 질문과 같은 확인은 몇 가지 세부 사항 누락하지만 JAX-WS RI를 사용하는 경우, 다음 Adding SOAP headers when sending requests에서 봐 가지고있다 :

이 일의 휴대용 방법은 당신이를 만들 이다 SOAPHandler 및 SAAJ와 을 엉망으로 만들었지 만 RI는 이것을 더 잘 수행하기 위해 을 제공합니다.

프록시를 만들거나 개체를 전달할 때 그들은 BindingProvider 인터페이스를 구현합니다. 에서 JAX-WS RI를 사용하면 WSBindingProvider으로 다운 캐스트 할 수 있으며 은 JAX-WS RI에서만 제공되는 몇 가지 방법을 더 정의합니다.

이 인터페이스를 사용하면 임의의 수의 헤더 객체 (각각 SOAP 헤더를 나타내는 )를 설정할 수 있습니다. 은 을 원한다면 직접 구현할 수 있지만 중 하나를 사용하면 Headers 클래스에 정의 된 팩토리 메소드 중 하나를 사용하여 만들 수 있습니다.

import com.sun.xml.ws.developer.WSBindingProvider; 

HelloPort port = helloService.getHelloPort(); // or something like that... 
WSBindingProvider bp = (WSBindingProvider)port; 

bp.setOutboundHeader(
    // simple string value as a header, like <simpleHeader>stringValue</simpleHeader> 
    Headers.create(new QName("simpleHeader"),"stringValue"), 
    // create a header from JAXB object 
    Headers.create(jaxbContext,myJaxbObject) 
); 

따라 업데이트 코드를 다시 시도하십시오. JAX-WS RI를 사용하지 않는 경우, 질문을 업데이트하고 더 많은 컨텍스트 정보를 제공하십시오.

업데이트 : 호출하려는 웹 서비스는 WS-Security/UsernameTokens로 보호됩니다. 이것은 초기 질문과 조금 다릅니다. 어쨌든, 사용자 이름과 암호를 보내도록 클라이언트를 구성하려면 위의 게시물 Implementing the WS-Security UsernameToken Profile for Metro-based web services (4 단계로 건너 뛰기)을 확인하는 것이 좋습니다. 이 단계에서 NetBeans를 사용하면 많은 작업을 쉽게 수행 할 수 있습니다. 당신이 당신의 프로젝트를 빌드 메이븐을 사용하는 경우

+1

이클립스에서이'com.sun.xml.internal.ws.developer.WSBindingProvider' 클래스를 가져올 수 없습니다. – pihentagy

+0

com.sum 패키지의 클래스를 사용할 경우 이식성 문제가 있습니까? – james2611nov

7

또한, 다음과 같은 종속성을 추가해야합니다 :

<dependency> 
     <groupId>com.sun.xml.ws</groupId> 
     <artifactId>jaxws-rt</artifactId> 
     <version>{currentversion}/version> 
    </dependency> 

이 클래스 com.sun.xml.ws.developer.WSBindingProvider을 제공합니다.

링크 : https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt 내 나쁜 영어

24

죄송합니다.데이터는 @WebParam (헤더 = TRUE) 그런를 사용하여 SOAP 헤더 (잭스 - WS)에 전송할 수 있습니다 :

당신은, SOAP 헤더와 함께 클라이언트를 생성하려는처럼 -XadditionalHeaders를 사용해야하는 경우
@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/") 
@Oneway 
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message") 
    Data message, 
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader") 
    Header serviceHeader); 

:

wsimport -keep -Xnocompile -XadditionalHeaders -Xdebug http://12.34.56.78:8080/TestHeaders/somewsdl?wsdl -d /home/evgeny/DEVELOPMENT/JAVA/gen 
당신이 웹 서비스를 @Oneway 필요가없는 경우

, 당신은 그렇게 홀더를 사용할 수 있습니다

@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/") 
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message") 
    Data message, 
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader") 
    Holder<Header> serviceHeader); 
+1

+1,'-XadditionalHeaders'는이 경우 중요한 속성입니다. –

+0

header = true 나를 위해 속임수를 사용했습니다. 기존 스텁을 복사하고 maven wsimport의 복사본에 header = true를 설정하여 생성 된 스텁을 덮어 쓰지 않도록했습니다. – Zeus

+0

-additionalHeader의 maven plugin에 해당하는 것은 무엇입니까? –

2

사용 받는다는 및 플러그인 jaxws-maven-plugin합니다. 그러면 웹 서비스 클라이언트가 생성됩니다. xadditionalHeaders을 true로 설정해야합니다. 그러면 헤더 입력이있는 메소드가 생성됩니다.

0

다른 답변이 없기 때문에이 답변을 추가하고 있습니다.

BindingProvider bp =(BindingProvider)basicHttpBindingAuthentication; 
bp.getBinding().getHandlerChain().add(new SOAPHeaderHandler(authenticatedToken)); 
bp.getBinding().getHandlerChain().add(new SOAPLoggingHandler()); 
0

jaxws-rt-2.2.10-ources.jar!\com\sun\xml\ws\transport\http\client\HttpTransportPipe.java에서 :

public Packet process(Packet request) { 
     Map<String, List<String>> userHeaders = (Map<String, List<String>>) request.invocationProperties.get(MessageContext.HTTP_REQUEST_HEADERS); 
     if (userHeaders != null) { 
      reqHeaders.putAll(userHeaders); 
난 그냥 처리기를 추가, 프록시에서

import java.util.Set; 
import java.util.TreeSet; 

import javax.xml.namespace.QName; 
import javax.xml.soap.SOAPElement; 
import javax.xml.soap.SOAPEnvelope; 
import javax.xml.soap.SOAPFactory; 
import javax.xml.soap.SOAPHeader; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> { 

    private final String authenticatedToken; 

    public SOAPHeaderHandler(String authenticatedToken) { 
     this.authenticatedToken = authenticatedToken; 
    } 

    public boolean handleMessage(SOAPMessageContext context) { 
     Boolean outboundProperty = 
       (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
     if (outboundProperty.booleanValue()) { 
      try { 
       SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope(); 
       SOAPFactory factory = SOAPFactory.newInstance(); 
       String prefix = "urn"; 
       String uri = "urn:xxxx"; 
       SOAPElement securityElem = 
         factory.createElement("Element", prefix, uri); 
       SOAPElement tokenElem = 
         factory.createElement("Element2", prefix, uri); 
       tokenElem.addTextNode(authenticatedToken); 
       securityElem.addChildElement(tokenElem); 
       SOAPHeader header = envelope.addHeader(); 
       header.addChildElement(securityElem); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } else { 
      // inbound 
     } 
     return true; 
    } 

    public Set<QName> getHeaders() { 
     return new TreeSet(); 
    } 

    public boolean handleFault(SOAPMessageContext context) { 
     return false; 
    } 

    public void close(MessageContext context) { 
     // 
    } 
} 

:

은 내가 프록시헤더 처리기를 추가했다

그래서, key MessageContext.HTTP_REQUEST_HEADERS 인 requestContext의 Map<String, List<String>>이 SOAP 헤더에 복사됩니다. Application Authentication with JAX-WS via headers

BindingProvider.USERNAME_PROPERTYBindingProvider.PASSWORD_PROPERTY 키 샘플 표준 기본 인증을 Authorization 헤더를 추가 HttpTransportPipe.addBasicAuth() 특별한 방식으로 처리된다.

Message Context in JAX-WS

0

당신이 사용하는 어떤 WS 스택 SOAP 헤더

BindingProvider prov = (BindingProvider)port; 
prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
       "your end point")); 
Map<String, List<String>> headers = new HashMap<String, List<String>>(); 
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername"); 
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword"); 
prov.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);