使用KSoap2连接到Android中的安全Web服务

时间:2012-02-21 15:02:44

标签: android web-services security ksoap2

我正在尝试使用KSoap2连接到Android应用中的安全网络服务,但遇到了一些困难。我已经在StackOverflow上查看了一些教程和其他问题/答案,但到目前为止还没有任何工作。

我在不安全的服务上有一个相同的web服务,我可以很好地连接到这个。我不确定是否需要手动设置SSL连接,或者在使用安全服务时KSoap2是否应该处理所有这些?

我正在尝试使用找到的解决方案here,但我收到以下错误:

java.io.IOException: Relative path:  
https://XXXXXXXX.net/FPSecureService/ClientService.svc

使用SoapUI时我可以连接到安全的webservice没问题 - 我必须设置用户名和密码,并将WSS-Password Type设置为“PasswordText”,然后它可以正常工作。我试图让我的Java代码尽可能地模仿SoapUI生成的请求代码。我添加的所有标题内容都是为了尝试使它与SoapUI生成的请求相同,但这没有用。

以下是调用Web服务的代码:

public void secureWebServiceCall(){

    // secure service
    String mUrl = "https://XXXXXXXX.net/FPSecureService/ClientService.svc"; 

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 

    String clientID = "XXXXXXX";

    PropertyInfo pi = new PropertyInfo();
    pi.setName("nationalID"); 
    pi.setValue(clientID); 
    pi.setType(clientID.getClass()); 
    request.addProperty(pi);

    // build Envelope
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
    envelope.dotNet = true;

    // Apdd mapping and marshalling
    envelope.addMapping(NAMESPACE, "GetClientByNationalID", new ClientID().getClass());
    Marshal floatMarshal = new MarshalFloat();
    floatMarshal.register(envelope); 


    // Construct soap envelope headers
    Element[] header = new Element[1];
    header[0] = new Element().createElement("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd","Security");
    header[0].setAttribute(null, "mustUnderstand","1");
    Element usernametoken = new Element().createElement("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "UsernameToken");
    usernametoken.setAttribute("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id", "UsernameToken-1");
    header[0].addChild(Node.ELEMENT,usernametoken);
    Element username = new Element().createElement(null, "n0:Username");
    username.addChild(Node.TEXT, "XXXXXXXX");
    usernametoken.addChild(Node.ELEMENT, username);
    Element pass = new Element().createElement(null, "n0:Password");
    pass.setAttribute(null, "Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
    pass.addChild(Node.TEXT, "XXXXXXX");
    usernametoken.addChild(Node.ELEMENT, pass);
    Element nonce = new Element().createElement(null, "n0:Nonce"); 
    nonce.setAttribute(null, "EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
    nonce.addChild(Node.TEXT, "eic5EdyTomcBLocwyph5Mw==");
    usernametoken.addChild(Node.ELEMENT, nonce);
    Element created = new Element().createElement(null, "n0:Created");
    created.addChild(Node.TEXT, "2012-02-08T09:47:55.225Z");
    usernametoken.addChild(Node.ELEMENT, created); 

    envelope.headerOut = header; 

    // Set Output Soap Object as Request
    envelope.setOutputSoapObject(request); 
    HttpTransportSE t = new HttpTransportSE(mUrl);
    AndroidInsecureKeepAliveHttpsTransportSE androidTransport = 
new AndroidInsecureKeepAliveHttpsTransportSE("XXXXXXXX.net", 80, mUrl, 50000);


    ClientID client = new ClientID(); 
    t.debug = true; 

    try { 
        Log.i("webServiceCall", "Trying call to web service");
        // t.call(SOAP_ACTION, envelope);
        androidTransport.call(SOAP_ACTION, envelope); 
        SoapObject response = (SoapObject) envelope.getResponse();
        TextView tv = (TextView) findViewById(R.id.textView1); 
        tv.setText(response.getPropertyAsString(3)); 

        Log.i("success", response.getPropertyAsString(0)); 
        Log.i("success", response.getPropertyAsString(1));
        Log.i("success", response.getPropertyAsString(2));
        Log.i("success", response.getPropertyAsString(3));
        Log.i("success", response.getPropertyAsString(4)); 
        System.out.println("Request: "  + t.requestDump); 
        System.out.println("Response: " + t.responseDump);

    } catch (Exception e) {
        Log.e("webServiceCall", "Error calling webservice.");
        e.printStackTrace(); 
        System.out.println("Request: "  + t.requestDump); 
        System.out.println("Response: " + t.responseDump);
    }

}

有没有人有任何想法?我觉得我可能最终会使用AndroidInsecureHttpsServiceConnection和所有SSL内容,但它不起作用。我不禁感到我在某个地方犯了一个简单的错误,但我不知道它是什么。那个“相对路径”错误让我感觉这对于我给出连接的参数来说非常简单,但是我对这些东西不熟悉并且不确定我应该指定哪些参数以及我应该如何指定它们。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

使用KeepAliveHttpsTransportSE项目中的ksaop2-android。它对我来说很好。

并确认该网址在设备上的浏览器上公开服务只是为了检查代理服务器的可用性等等。

从您的代码中,很可能会导致问题:

 HttpTransportSE t = new HttpTransportSE(mUrl);
    AndroidInsecureKeepAliveHttpsTransportSE androidTransport = 
new AndroidInsecureKeepAliveHttpsTransportSE("XXXXXXXX.net", 80, mUrl, 50000);

不要在另一个地方使用一个交通工具。而是仅使用构造函数或AndroidInsecureKeepAliveHttpsTransportSE。构造函数进行了一些初始化,如果你重用它们,它很可能会进行初始化。

答案 1 :(得分:0)

此网站:http://obtao.com/blog/2013/09/how-to-use-wsse-in-android-app/ 解释了如何生成随机数,对其进行编码,并将其包含在标头中。如果你从soapui复制nonce,它应该在后端失败,因为nonce的重点是防止这样的重放。您需要生成自己的,如引用的示例所示。