没有签名令牌Java CXF客户端

时间:2014-11-07 23:42:31

标签: java web-services wcf cxf cxf-codegen-plugin

我正在尝试用Apache-CXF-2.7.11构建一个与.NET WCF服务通信的Java客户端。

我的Java客户端代码如下,客户端是自动生成IDE,只有我从CXF文档中复制的凭据。

public static void main(String args[]) throws java.lang.Exception {
    URL wsdlURL = Reportes.WSDL_LOCATION;
    if (args.length > 0 && args[0] != null && !"".equals(args[0])) { 
        File wsdlFile = new File(args[0]);
        try {
            if (wsdlFile.exists()) {
                wsdlURL = wsdlFile.toURI().toURL();
            } else {
                wsdlURL = new URL(args[0]);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    Reportes ss = new Reportes(wsdlURL, SERVICE_NAME);
    IReportes port = ss.getWSHttpBindingIReportes();

    Client client = ClientProxy.getClient(port);
    Endpoint cxfEndpoint = client.getEndpoint();

    Map ctx = ((BindingProvider)port).getRequestContext();
    ctx.put("ws-security.username", "username");
    ctx.put("ws-security.password", "password");

    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(ctx);
    cxfEndpoint.getOutInterceptors().add(wssOut);

    {
    System.out.println("Invoking programaProveedores...");
    java.lang.String _programaProveedores_idBeneficiario = "";
    com.wsclient.ArrayOfProgramaProveedor _programaProveedores__return = port.programaProveedores(_programaProveedores_idBeneficiario);
    System.out.println("programaProveedores.result=" + _programaProveedores__return);


    }
System.exit(0);
}

结果是一个例外:

Advertencia: Interceptor for {http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}SecurityTokenService#{http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl}RequestSecurityToken has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: No signature token
at org.apache.cxf.ws.security.wss4j.policyhandlers.SymmetricBindingHandler.doSignBeforeEncrypt(SymmetricBindingHandler.java:398)
at org.apache.cxf.ws.security.wss4j.policyhandlers.SymmetricBindingHandler.handleBinding(SymmetricBindingHandler.java:124)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:173)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:90)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
at org.apache.cxf.ws.security.trust.AbstractSTSClient.issue(AbstractSTSClient.java:782)
at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:62)
at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:56)
at org.apache.cxf.ws.security.trust.STSClient.requestSecurityToken(STSClient.java:52)
at org.apache.cxf.ws.security.policy.interceptors.SecureConversationOutInterceptor.issueToken(SecureConversationOutInterceptor.java:167)
at org.apache.cxf.ws.security.policy.interceptors.SecureConversationOutInterceptor.handleMessage(SecureConversationOutInterceptor.java:69)
at org.apache.cxf.ws.security.policy.interceptors.SecureConversationOutInterceptor.handleMessage(SecureConversationOutInterceptor.java:44)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:570)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:479)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:382)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:335)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:135)
at com.sun.proxy.$Proxy38.programaProveedores(Unknown Source)
at com.wsclient.IReportes_WSHttpBindingIReportes_Client.main(IReportes_WSHttpBindingIReportes_Client.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.apache.cxf.ws.policy.PolicyException: No signature token

还有其他设置用户名令牌的方法吗?

对不起我的英文...

1 个答案:

答案 0 :(得分:1)

我发现了问题,我想要做的是从Java客户端导入WCF创建的WSDL,最初我使用wsimport,之后我使用Metro 2.3.0并且我得到了以下错误:

Advertencia: SP0100: Policy assertion Assertion[com.sun.xml.ws.policy.sourcemodel.DefaultPolicyAssertionCreator$DefaultPolicyAssertion] {
assertion data {
    namespace = 'http://schemas.microsoft.com/ws/2005/07/securitypolicy'
    prefix = 'mssp'
    local name = 'SslContextToken'
    value = 'null'
    optional = 'false'
    ignorable = 'false'
    attributes {
        name = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy:IncludeToken', value = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient'
    }
}
no parameters
nested policy {
    namespace version = 'v1_5'
    id = 'null'
    name = 'null'
    vocabulary {
        1. entry = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy:RequireDerivedKeys'
    }
    assertion set {
        Assertion[com.sun.xml.ws.policy.sourcemodel.DefaultPolicyAssertionCreator$DefaultPolicyAssertion] {
            assertion data {
                namespace = 'http://schemas.xmlsoap.org/ws/2005/07/securitypolicy'
                prefix = 'sp'
                local name = 'RequireDerivedKeys'
                value = 'null'
                optional = 'false'
                ignorable = 'false'
                no attributes
            }
            no parameters
            no nested policy
        }
    }
}
} is not supported under Token assertion. 

原因是WCF WS-Policy正在构成这一部分:

<mssp:SslContextToken 
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" xmlns:mssp="http://schemas.microsoft.com/ws/2005/07/securitypolicy">
  <wsp:Policy>
    <sp:RequireDerivedKeys/>
  </wsp:Policy>
</mssp:SslContextToken>

这意味着您的WCF服务使用X.509证书协商。在这种情况下,客户端使用服务器X.509证书进行加密。这里的独特之处在于客户端不需要带外此证书(在大多数情况下),而是使用SOAP级协商获得此证书。这是作为WS-Trust的扩展实现的。虽然这不是严格意义上的Microsoft专有解决方案,但到目前为止,微软是唯一一个实施它的解决方案。简而言之 - X.509协商(SslContextToken)不可互操作。要关闭它,请更新您的WsHttpBinding配置:

<bindings>
    <wsHttpBinding>
        <binding>
            <security mode="Message">
                <message clientCredentialType="None" negotiateServiceCredential="false" />
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

或者在CustomBinding中选择正确的方案:

<security authenticationMode="AnonymousForCertificate">
   <secureConversationBootstrap />
</security>

您还可以使用等效案例进行用户名验证。请注意,任何客户端(包括WCF客户端)现在都需要在带外定义服务证书。

此问题的引用是http://webservices20.blogspot.mx/2008/10/interoperability-gotcha-sslcontexttoken.html