![](/img/trans.png)
[英]Authentication between Android app and web service + facebook login
[英]Call web service with authentication (login and password) from android app
从过去的几天开始,我一直在研究Android代码以调用本地Web服务。 我正在使用适用于Android的ksoap2库“ ksoap2-android-assembly-2.5.7-jar-with-dependencies.jar”来调用在.NET中创建的SOAP Web服务。问题是,在请求特定功能之前,我需要进行身份验证使用基本http请求的客户端。
这是我的代码:
public String CallSoapConnexion(String login, String mdp) {
SoapObject request = new SoapObject(nms, mth);
PropertyInfo pi = new PropertyInfo();
pi.setName("login");
pi.setValue(login);
pi.setType(String.class);
request.addProperty(pi);
pi = new PropertyInfo();
pi.setName("mdp");
pi.setValue(mdp);
pi.setType(String.class);
request.addProperty(pi);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE httpTransport = new HttpTransportSE(urlHttp);
List<HeaderProperty> headerList = new ArrayList<HeaderProperty>();
headerList
.add(new HeaderProperty("Authorization", "Basic "
+ org.kobjects.base64.Base64.encode("login:pasword"
.getBytes())));
Object response = null;
try {
httpTransport.call(act, envelope, headerList);
response = envelope.getResponse();
} catch (Exception ex) {
return ex.toString;
}
return ex.toString;
}
但是我得到以下异常:
org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope (position:START_TAG <html>@2:7 in java.io.InputStreamReader@44f66cb0)
Ksoap2给我带来了很多麻烦,最终我使用SAXparser创建了自己的解析器,这是解析XML的最快方法。 这就是我做的。
首先,在类中,保存了WebServices所需的所有常量参数。 它们都是公共的和静态的,因此我可以在项目中的任何地方访问它们,而无需实例化类。 我们称之为MyConstants.class
//######################## LOGIN WEB SERVICE CONSTANTS
/**
* This string constructs the SOAP Envelope you need to use to Use the DoLogin WebService.
* Use this string with String.format in the following way.
* @param sUserName (String)
* @param sPassword (String)
* @Example String env = String.format(WebserviceConsumer.LOGIN_ENVELOPE, username, password);
* */
public static final String LOGIN_ENVELOPE = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<Login xmlns=\"webServiceNamespace\">" +
"<sUsername>%s</sUsername>" +
"<sPassword>%s</sPassword>" +
"</Login>" +
"</soap:Body>" +
"</soap:Envelope>";
public static final String LOGIN_SOAP_ACTION = "webServiceNamespace/Login";
public static final String LOGIN_URL = "https://ws.yoururl.com/YourLoginPage.asmx?op=Login";
public static final int LOGIN = 100;
这就是我“完成”的解析器。 它基于我发现的另一个解析器,所以我不知道它是否完美,但是效果很好。
[编辑]一段时间后我更改了解析器,因为SAX解析器不是一个好方法。 它速度很快,但是效率不高,因为它会创建很多对象,然后这些对象必须由垃圾收集器收集。 Google建议使用XMLPullParser来完成这项工作。 它的用法比SAX还要容易。 [/编辑]
package com.yourproject.parsers;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.os.Bundle;
/**Callback Example
* @example
* <?xml version="1.0" encoding="utf-8"?>
* <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
* <soap:Body>
* <LoginResponse xmlns="https://ws.yoururl.com/" >
* <LoginResult>
* <ROOT xmlns="" >
* <PassportKey>
* <Key>653215989827346254362544623544652321</Key>
* <otherLoginInfo>585051</otherLoginInfo>
* </PassportKey>
* </ROOT>
* </LoginResult>
* </LoginResponse>
* </soap:Body>
* </soap:Envelope>
*/
/**
* The loginParser saves the parsed data in a bundle. Once the parsing is done, call the
* getResutl() function to get a bundle that has the login authentication result.
* */
public class LoginParser extends DefaultHandler {
private String foundData = "";
private String authCode = "";
private String otherInfo = "";
private Bundle result;
public synchronized void parse(InputStream is) throws ParserConfigurationException, SAXException, IOException{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
xr.setContentHandler(this);
xr.parse(new InputSource(is));
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
foundData += new String(ch, start, length);
}
@Override
public void startDocument() throws SAXException{
// Nothing to do
}
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException{
foundData = "";
}
@Override
public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
if (qName.equals("Key")) {
authCode = foundData;
} else if (qName.equals("otherLoginInfo")){
otherInfo = foundData;
}
}
@Override
public void endDocument() throws SAXException{
// Nothing to do.
}
public Bundle getResult(){
result = new Bundle();
result.putString("authCode", authCode);
result.putString("otherInfo", otherInfo);
return result;
}
}
现在是使用解析器的类。 一旦有了这个,就可以在您喜欢的项目中的任何地方调用它。
package com.yourproject.web;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;
import com.yourproject.parsers.LoginParser;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
/**
* Public class used to send a SOAP message to our Webservices.
*
* Code from
* http://mobileorchard.com/android-app-development-calling-web-services/
* */
public class WebserviceCall{
LoginParser lp;
[... other parsers ...]
[... other parsers implementation ...]
public Bundle CallWebServiceParseAndReturn(String url, String soapAction, String envelope, int callerRequest) throws Exception {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpRequest = null;
HttpResponse httpResponse = null;
Bundle result = null;
httpRequest = new HttpPost(url);
if (envelope != null) {
httpRequest.setEntity(new StringEntity(envelope));
httpRequest.addHeader("Content-Type", "text/xml; charset=utf-8");
}
httpResponse = httpclient.execute(httpRequest);
switch (callerRequest) {
case MyConstants.LOGIN:
lp = new LoginParser();
lp.parse(httpResponse.getEntity().getContent());
result = lp.getResult();
break;
case MyConstants.OTHERPARSERS:
case default:
break;
return result;
}
}
最后,这是一个如何在项目中使用它的示例。
private void callWebserviceLogin(String userName, String password) {
try{
Bundle result = null;
WebserviceCall wsCall = new WebserviceCall();
String wsEnvelope = String.format(MyConstants.LOGIN_ENVELOPE, userName, password);
result = wsCall.CallWebServiceParseAndReturn(MyConstants.LOGIN_URL, MyConstants.LOGIN_SOAP_ACTION, wsEnvelope, MyConstants.LOGIN);
authenticationResult = result.getString("authCode");
} catch (Exception e) {
authenticationResult = "";
Log.e("Login error", e.getMessage());
}
}
如果您看到我拥有的包络常数,则字符串中会有一些%s标记。 当我使用String.format时,它会按照出现顺序将第一个标记之后的参数替换为每个标记(此标记是保存标记的字符串)。
我知道这不是您所期望的,但希望对您有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.