2014-11-26 16 views
1

우리는 다음 SOAP 메시지를받는 웹 서비스를 가지고있다. 나는 그것이 우리의 문제를위한 중요한 부분이라는 헤더 만 올리고있다.Spring-WS가 서명을 검증하고 엔드 포인트에서 SOAP 헤더를 추출한다.

<SOAP-ENV:Header> 
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1"> 
    <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-65E18DC0CA7D9A38B214168992655731">THE_CERTIFICATE</wsse:BinarySecurityToken> 
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-65E18DC0CA7D9A38B214168992656685"> 
    <ds:SignedInfo> 
     <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> 
     <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENV"/> 
     </ds:CanonicalizationMethod> 
     <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 
     <ds:Reference URI="#id-65E18DC0CA7D9A38B214168992656044"> 
     <ds:Transforms> 
      <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> 
      <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList=""/> 
      </ds:Transform> 
     </ds:Transforms> 
     <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
     <ds:DigestValue>DIGEST_VALUE</ds:DigestValue> 
     </ds:Reference> 
    </ds:SignedInfo> 
    <ds:SignatureValue>THE_SIGNATURE</ds:SignatureValue> 
    <ds:KeyInfo Id="KI-65E18DC0CA7D9A38B214168992655892"> 
     <wsse:SecurityTokenReference wsu:Id="STR-65E18DC0CA7D9A38B214168992655893"> 
     <wsse:Reference URI="#X509-65E18DC0CA7D9A38B214168992655731" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/> 
     </wsse:SecurityTokenReference> 
    </ds:KeyInfo> 
    </ds:Signature> 
</wsse:Security> 

인증서는 청원이 다음 구성 (서버 측)와 스프링에 의해 검증에 서명하는 데 사용 :

<sws:interceptors> 
    <bean class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"> 
     <property name="validationActions" value="Signature" /> 
     <property name="validationSignatureCrypto"> 
      <bean 
       class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean"> 
       <property name="keyStorePassword" value="passtrustore" /> 
       <property name="keyStoreLocation" value="classpath:/ts-webservice.jks" /> 
      </bean> 
     </property> 
     <property name="securementActions" value="Signature" /> 
     <property name="securementUsername" value="user" /> 
     <property name="securementPassword" value="pass" /> 
     <property name="securementSignatureKeyIdentifier" value="DirectReference" /> 
     <property name="securementSignatureCrypto"> 
      <bean 
       class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean"> 
       <property name="keyStorePassword" value="passkeystore" /> 
       <property name="keyStoreLocation" value="classpath:/ks-webservice.jks" /> 
      </bean> 
     </property> 
    </bean> 
</sws:interceptors> 

모든 것이 잘 작동하지만 우리는 binarySecurityToken를 추출하기 위해 노력하고있다 왜냐하면 우리는 그 인증서를 사용하여 서명자의 ID를 얻고 응답에서 일부 개인 정보를 반환하기 때문입니다. 이 메소드의 입력 매개 변수로 다시 추가 할 수 있지만 헤더에 이미있는 경우 동일한 인증서를 두 번 보내지 않으려합니다.

요청을 반환하는 방법입니다 onee 다음 :

@PayloadRoot(localPart = "ValidateUserRequest", namespace = GET_TARGET_NAMESPACE) 
public @ResponsePayload 
ValidateUserResponse validateUser(@RequestPayload ValidateUserRequest request, MessageContext messageContext) throws WSSecurityException, 
     CertificateException { 
    // read SOAP Header 
    SoapMessage mc = (SoapMessage) messageContext.getRequest(); 
    String soapNamespace = WSSecurityUtil.getSOAPNamespace(mc.getDocument().getDocumentElement()); 
    Element elem = WSSecurityUtil.getDirectChildElement(mc.getDocument().getDocumentElement(), WSConstants.ELEM_HEADER, soapNamespace); 

    // get the BinarySignature tag 
    // FIRST getFirstChild() is NULL if we have validated the request 
    Node binarySignatureTag = elem.getFirstChild().getFirstChild(); 
    BinarySecurity token = new X509Security((Element) binarySignatureTag); 

    InputStream in = new ByteArrayInputStream(token.getToken()); 
    CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 
    X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in); 

    // do stuff with the certificate and return values 
} 
봄 요청의 서명을 검증

, 그것은 헤더를 제거하는 것 같다, 그래서 우리는 헤더의 첫 번째 자식에 액세스 할 수 없습니다 요소. 응용 프로그램 컨텍스트에서 유효성 검사 부분에 주석을 달면 이전 코드는 매력처럼 작동하고 인증서를 얻습니다.

이 동작을 어떻게 피할 수 있습니까? 유효성 검사 후에 요청의 헤더가 제거되는 이유는 무엇입니까?

감사합니다.

답변

0

오랜 밤에 Spring 문서를 읽고 읽은 후에 해결 방법을 발견했습니다. 봄이 헤더를 소비하는 이유를 이해하지 않거나 내 엔드 포인트가 헤더를 수신되지 않는 이유, 그러나 우리는 (활성화 서명 유효성 검사) 다음 코드를 사용하여 인증서를 추출 할 수있다 : 일부 연구 후

@PayloadRoot(localPart = "ValidateUserRequest", namespace = GET_TARGET_NAMESPACE) 
public @ResponsePayload ValidateUserResponse validateUser(@RequestPayload ValidateUserRequest request, MessageContext messageContext) throws WSSecurityException, CertificateException { 
    List<WSHandlerResult> handlerResults = (List<WSHandlerResult>) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS); 
    WSHandlerResult rResult = handlerResults.get(0); 
    List<WSSecurityEngineResult> results = rResult.getResults(); 

    WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN); 

    X509Certificate returnCert = null; 
    if (actionResult != null) { 
     returnCert = (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE); 
    } 
// do stuff with the certificate and return values 
} 

을 나는 봄이 MessageContext에 인증서가 저장되어있는 유효성 검사에서 처리 된 것을 발견했다. (Wss4jSecurityInterceptor#updateContextWithResults 참조).

+0

AOP를 사용하여'messageContext' 매개 변수의 유효성을 검사하는 것이 더 좋지 않습니까? – EliuX