[置顶] Android 用户远程验证----XFIRE,BASE64,KSOAP,WEBSERVICE

  在Android开发过程中,不一定都用本地文件系统或本地数据库SQLite,比如QQ,用户的帐号数据都存储远程服务器上。而访问远程数据库有很多种方式,比如HTTPCLIENT,WEBSERVICE,SOCKET等多种方式,即分别为http通信,webservice(Web服务通信),还有socket套接字通信等等,限于篇幅,本文我只讲解讲一下webservice方式。其他方式,在其他的文档在讲。

 

第一步,在要android中使用web服务,我们得先配置好web服务 器端。我使用了java webservice---XFIRE框架。

相信XFire的优点不用多说,google,百度一下就知道了。我这里主要讲解配置过程。配置一个简单的webservice,相信配置了该webservice。

 

xfire使用接口和接口实现类来实现远程方法提拱。这样可以将接口公布给客户端,但android提拱了ksoap框架类,一种全新的实现方式,就不需要使用远程接口。只要配置好相关参数和方法即可。

 

废话不多说了,帖上代码:

//将 POJO 发布成 Web 服务:有两种方法,接口和实现类是其中之一 public interface IAccount { public int account(int x,int y); public String helloWorld(String str); //访问mysql数据库 public int login(String username,String password); }

 

这个是接口类,再帖出实现类。

public class AccountImp implements IAccount { public int account(int x, int y) { // TODO Auto-generated method stub return x*y; } public String helloWorld(String str) { // TODO Auto-generated method stub return str; } public int login(String username, String password) { // TODO Auto-generated method stub String decodeusername="",decodepassword=""; //对密码进行解密码 try { decodeusername=new String(com.base.encry.decry.app.Base64.decode(username)); decodepassword=new String(com.base.encry.decry.app.Base64.decode(password)); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } ConnDB connDB=new ConnDB(); return connDB.login(decodeusername, decodepassword); } }

 

下面我着重讲一下login方法,它里面有两个类提拱方法以实现其功能。

Base64算法相信大家都比较熟悉吧,dt.jar已经提拱了具体的实现细节。你可以查阅相关文档和源码,

这里为了让大家费时费力,我贴上代码。

 

public class Base64 { private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 }; public static void main(String[] args) { String string="徐忠明"; String encodeStr=encode(string.getBytes()); byte[] bytesStr=null; try { bytesStr=decode(encodeStr); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(encodeStr); System.out.println(new String(bytesStr)); } // 编码 public static String encode(byte[] data) { StringBuffer sb = new StringBuffer(); int len = data.length; int i = 0; int b1, b2, b3; while (i < len) { b1 = data[i++] & 0xff; if (i == len) { sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[(b1 & 0x3) << 4]); sb.append("=="); break; } b2 = data[i++] & 0xff; if (i == len) { sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); sb.append(base64EncodeChars[(b2 & 0x0f) << 2]); sb.append("="); break; } b3 = data[i++] & 0xff; sb.append(base64EncodeChars[b1 >>> 2]); sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]); sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]); sb.append(base64EncodeChars[b3 & 0x3f]); } return sb.toString(); } // 解码 public static byte[] decode(String str) throws UnsupportedEncodingException { StringBuffer sb = new StringBuffer(); byte[] data = str.getBytes("US-ASCII"); int len = data.length; int i = 0; int b1, b2, b3, b4; while (i < len) { /* b1 */ do { b1 = base64DecodeChars[data[i++]]; } while (i < len && b1 == -1); if (b1 == -1) break; /* b2 */ do { b2 = base64DecodeChars[data[i++]]; } while (i < len && b2 == -1); if (b2 == -1) break; sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4))); /* b3 */ do { b3 = data[i++]; if (b3 == 61) return sb.toString().getBytes("iso8859-1"); b3 = base64DecodeChars[b3]; } while (i < len && b3 == -1); if (b3 == -1) break; sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); /* b4 */ do { b4 = data[i++]; if (b4 == 61) return sb.toString().getBytes("iso8859-1"); b4 = base64DecodeChars[b4]; } while (i < len && b4 == -1); if (b4 == -1) break; sb.append((char) (((b3 & 0x03) << 6) | b4)); } return sb.toString().getBytes("iso8859-1"); } }

 

这段代码可以也可以在Android客户端重用,Android端负责加密码,而XFire服务器端负责解密,这样做是为了安全性着想。

你想想如果不加密码,直接将帐号和密码在网络上传输,裸露在Internet中,那是多么的危险,这是用了通用的Base64加密解密码算法也不一定安全。我只是做一个试笵,大家可以根据自已需要来选用自已的加密码算法。比如md5,SHA等等。

 

 

还有就是访问数据库的细节,在这里只用了原始了JDBC,当然可以扩展成Hibernate,iBatis.为求简单原始。帖上如下代码:

 

package com.db.app; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import com.constants.util.Constants; import com.sun.corba.se.impl.orbutil.closure.Constant; public class ConnDB { public ConnDB(){ } public Connection getConnection(){ Connection conn=null; try{ Class.forName("com.mysql.jdbc.Driver"); conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456"); }catch (Exception e) { // TODO: handle exception } return conn; } /** * 功能:用户登陆验证 * @param username 用户名 * @param password 密码 * @return * 首先判断是否存在该用户,如果不存在,则返回false, * 如果存在该用户,则判断密码是否正确,如果不正确,则返回密码输入错误 */ public int login(String username,String password){ try{ PreparedStatement ps=getConnection().prepareStatement("select * from t_customer where account=?"); ps.setString(1, username); ResultSet rs=ps.executeQuery(); if(!rs.next()){ return Constants.INVALID_NAME;//"该用户不存在,请输入你的用户名"; } ps=getConnection().prepareStatement("select * from t_customer where account=? and password=?"); ps.setString(1, username); ps.setString(2, password); rs=ps.executeQuery(); if (!rs.next()) { return Constants.INVALID_PASSWORD;//"密码输入错误,请核对"; } else return Constants.VALID_USERNAME_PASSWORD;//"验证通过"; }catch(Exception evt){ evt.printStackTrace(); return Constants.INVALID_DATABASE;//"数据库出现异常,请重试"; } } public static void main(String[] args) { ConnDB connDB=new ConnDB(); System.out.println(connDB.login("fda", "123")); System.out.println(connDB.login("001", "123456")); System.out.println(connDB.login("001", "123")); } }

不用多说,地球都可以看懂它们。呵呵。

 

 

当然要将这个类中的方法发布出去还要有Services.xml文件,这个文件的存储路径为:WebServices目录下。即项目的根目录下面。

代码如下所示:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xfire.codehaus.org/config/1.0"> <!-- 服务一:简单计算,直接输出 --> <service> <name>MyService</name> <serviceClass>test.IAccount</serviceClass> <implementationClass>test.AccountImp</implementationClass> <mce:style><!-- wrapped --></mce:style><style mce_bogus="1">wrapped</style> <use>literal</use> <scope>application</scope> <namespace>http://android.googlepages.com/</namespace> </service> <!--服务二:访问数据库,功能:由用户帐号直接得到其密码,如果帐号不对则提示重新输入 <service> <name>MyDbService</name> <serviceClass>test.IConnDb</serviceClass> <implementationClass>test.ConnDbImp</implementationClass> <mce:style><!-- wrapped --></mce:style><style mce_bogus="1">wrapped</style> <use>literal</use> <scope>application</scope> <namespace>http://android.googlepages.com/</namespace> </service> --> </beans>

我为了简单,写只了一个MyService服务。你可以根据自已需要添加其他的服务。

 

当然运行这个还要有一些JAR包的支持。我附图,如下所示:

[置顶] Android 用户远程验证----XFIRE,BASE64,KSOAP,WEBSERVICE_第1张图片

 

布署这个webservice,很简单,就像布署web project一样布署即可。然后运行一下web服务器(tomcat),如下所示:

[置顶] Android 用户远程验证----XFIRE,BASE64,KSOAP,WEBSERVICE_第2张图片

 

 

这样Web service就发布成功了。我们可以看到login方法。

 

接下来我们看看Android客户端。要使用webservice框架,我们要在classpath中导入D:/学习专题/Android专题/Android例程专题(自定收集)/Android WebService/android/android webservice/ksoap2_android_src.zip。

 

这样才可以运行webservice

 

贴上代码:

 

package com.cn.blogs.ksoap.app; import java.io.IOException; import org.kobjects.base64.Base64; import org.ksoap2.SoapEnvelope; import org.ksoap2.serialization.SoapObject; import org.ksoap2.serialization.SoapPrimitive; import org.ksoap2.serialization.SoapSerializationEnvelope; import org.ksoap2.transport.AndroidHttpTransport; import org.ksoap2.transport.HttpTransportSE; import org.xmlpull.v1.XmlPullParserException; public class MyWebServiceHelper { // WSDL文档中的命名空间 private static final String targetNameSpace = "http://android.googlepages.com/"; // WSDL文档中的URL private static final String WSDL = "http://10.10.178.70:8888/WSDLApp/services/MyService"; // 需要调用的方法名(获得Myervices中的helloWorld方法) private static final String getHelloworld = "helloWorld"; //需要调用的方法名(获得Myervices中的login方法) private static final String getLogin="login"; /******** * 获得自定义WebService XFire框架信息 * * @return */ public static void main(String[] args) { MyWebServiceHelper webServiceHelper=new MyWebServiceHelper(); // System.out.println(webServiceHelper.getHelloworldStr("/"你好,ksoap webservice 框架/"")); System.out.println(webServiceHelper.getFlagFromDBCust("001","123")); } public String getHelloworldStr(String string) { String str = ""; SoapObject soapObject = new SoapObject(targetNameSpace, getHelloworld); soapObject.addProperty("str", string); //调用的方法参数与参数值(根据具体需要可选可不选) SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); envelope.dotNet = false; //不使用dotnet webservice; envelope.setOutputSoapObject(soapObject);//envelope.bodyOut=request; AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL); //HttpTransportSE httpTranstation=new HttpTransportSE(WSDL); try { httpTranstation.call(targetNameSpace + getHelloworld, envelope); SoapPrimitive result = (SoapPrimitive ) envelope.getResponse(); // 下面对结果进行解析,结构类似json对象 // str=(String) result.getProperty(6).toString(); // int count = result.getPropertyCount(); // for (int index = 0; index < count; index++) { // provinces.add(result.getProperty(index).toString()); // System.out.println(result.getProperty(index).toString()); // } str=result.toString(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str; } public String getFlagFromDBCust(String username,String password) { String str = ""; SoapObject soapObject = new SoapObject(targetNameSpace,getLogin); //给帐号和密码加密码 String encodeUsername=Base64.encode(username.getBytes()); String encodePassword=Base64.encode(password.getBytes()); soapObject.addProperty("username", encodeUsername); soapObject.addProperty("password",encodePassword); //调用的方法参数与参数值(根据具体需要可选可不选) SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.dotNet = false; envelope.setOutputSoapObject(soapObject); HttpTransportSE httpTranstation=new HttpTransportSE(WSDL); //或者AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL); try { httpTranstation.call(targetNameSpace + getLogin, envelope); SoapObject result = (SoapObject ) envelope.bodyIn;//getResponse(); // str=(String) result.getProperty(0).toString(); // 也可以通过下面方式获得str // SoapPrimitive result = (SoapPrimitive ) envelope.getResponse(); // str=result.toString(); // 直指value字符串值 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return str; } }

 

可以看到Base64又在这里出现了,主要是为了加密码,然后传送给服务器端

 

 

注意:private static final String WSDL = "http://10.10.178.70:8888/WSDLApp/services/MyService";

而不要在后面加上?wsdl,如果加上了就错误了。

 

里面的代码。你可以下载源码进行解读。

我来提一点两种方式获得:result

 

HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
        //或者AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL);

 

 

这两种都可以

 

 

然后还有

 


            httpTranstation.call(targetNameSpace + getLogin, envelope);
            SoapObject  result = (SoapObject ) envelope.bodyIn;//getResponse();
            //
           
            str=(String) result.getProperty(0).toString();
           
              //  也可以通过下面方式获得str
             //  SoapPrimitive  result = (SoapPrimitive ) envelope.getResponse();
            //    str=result.toString();
           //   直指value字符串值

 

 

这两种方式,我在测试的过程中都通过。提拱多种方式,让程序员灵活使用。

 

下面我贴上Activity子类MainActivity

 

package com.net.connect.app; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.cn.blogs.ksoap.app.MyWebServiceHelper; /**** * http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html * * @author mingg * */ public class LoginActivity extends Activity { /** Called when the activity is first created. */ TextView txtUsername,txtPassword; EditText etUsername,etPassword; Button loginButton,exitButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); constructLayout(); } private void constructLayout() { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); LinearLayout.LayoutParams controlpl = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); LinearLayout ll = new LinearLayout(this); ll.setOrientation(LinearLayout.VERTICAL); txtUsername = new TextView(this); txtUsername.setText("帐号:/t"); etUsername = new EditText(this); txtPassword = new TextView(this); txtPassword.setText("密码:/t"); etPassword = new EditText(this); loginButton=new Button(this); loginButton.setText("登陆"); loginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String userValue=etUsername.getText().toString(); String passValue=etPassword.getText().toString(); if(userValue.length()==0 || passValue.length()==0){ Toast.makeText(LoginActivity.this, "帐号和密码不能为空,请输入", Toast.LENGTH_LONG).show(); return; } //调用自已写的webService MyWebServiceHelper webServiceHelper=new MyWebServiceHelper(); int flag=Integer.parseInt(webServiceHelper.getFlagFromDBCust(userValue,passValue)); String content=""; switch (flag) { case 1 : content="该用户不存在,请输入你的用户名"; Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show(); break; case 2 : content="密码输入错误,请核对"; Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show(); break; case 3 : content="数据库出现异常,请重试"; Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show(); break; case 4 : content="验证通过"; Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show(); try { Thread.currentThread().sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //转到MainActivity Intent intent=new Intent(); intent.setClass(LoginActivity.this, MainActivity.class); startActivity(intent); break; default: break; } } }); exitButton=new Button(this); exitButton.setText("退出"); exitButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub LoginActivity.this.finish(); //退出 } }); ll.addView(txtUsername, controlpl); ll.addView(etUsername, controlpl); ll.addView(txtPassword, controlpl); ll.addView(etPassword, controlpl); ll.addView(loginButton, controlpl); ll.addView(exitButton, controlpl); addContentView(ll, lp); } }

 

最终运行效果如下所示:

有点小问题,可以在开发中更正。

 

最终不要忘了加 internet permmition  

 

AndroidManifest.xml中加入<uses-permission android:name="android.permission.INTERNET" />

 

 

 

[置顶] Android 用户远程验证----XFIRE,BASE64,KSOAP,WEBSERVICE_第3张图片


 

 

 

 

 

你可能感兴趣的:(exception,数据库,android,webservice,String,web服务)