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方法,它里面有两个类提拱方法以实现其功能。
 
本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文连接:http://www.linuxidc.com/Linux/2011-04/35011.htm
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客户端。要使用webservice框架,咱们要在classpath中导入D:/学习专题/Android专题/Android例程专题(自定收集)/Android WebService/android/android webservice/ksoap2_android_src.zip。html

这样才能够运行webservicejava

贴上代码:mysql

  1. package com.cn.blogs.ksoap.app;
  2. import java.io.IOException;
  3. import org.kobjects.base64.Base64;
  4. import org.ksoap2.SoapEnvelope;
  5. import org.ksoap2.serialization.SoapObject;
  6. import org.ksoap2.serialization.SoapPrimitive;
  7. import org.ksoap2.serialization.SoapSerializationEnvelope;
  8. import org.ksoap2.transport.AndroidHttpTransport;
  9. import org.ksoap2.transport.HttpTransportSE;
  10. import org.xmlpull.v1.XmlPullParserException;
  11. public class MyWebServiceHelper {
  12.  // WSDL文档中的命名空间
  13.  private static final String targetNameSpace ="http://Android.googlepages.com/";
  14.  // WSDL文档中的URL
  15.  private static final String WSDL ="http://10.10.178.70:8888/WSDLApp/services/MyService";
  16.  // 须要调用的方法名(得到Myervices中的helloWorld方法)
  17.  private static final String getHelloworld = "helloWorld";
  18.  //须要调用的方法名(得到Myervices中的login方法)
  19.  private static final String getLogin="login";
  20.  /********
  21. * 得到自定义WebService XFire框架信息
  22. *
  23. * @return
  24. */
  25.  public static void main(String[] args) {
  26. MyWebServiceHelper webServiceHelper=newMyWebServiceHelper();
  27.  // System.out.println(webServiceHelper.getHelloworldStr("\"你好,ksoap webservice 框架\""));
  28. System.out.println(webServiceHelper.getFlagFromDBCust("001","123"));
  29. }
  30.  public String getHelloworldStr(String string) {
  31. String str = "";
  32. SoapObject soapObject = new SoapObject(targetNameSpace,
  33. getHelloworld);
  34. soapObject.addProperty("str", string);
  35.  //调用的方法参数与参数值(根据具体须要可选可不选)
  36. SoapSerializationEnvelope envelope = newSoapSerializationEnvelope(
  37. SoapEnvelope.VER11);
  38. envelope.dotNet = false//不使用dotnet webservice;
  39. envelope.setOutputSoapObject(soapObject);//envelope.bodyOut=request;
  40. AndroidHttpTransport httpTranstation = newAndroidHttpTransport(WSDL);
  41.  //HttpTransportSE httpTranstation=new HttpTransportSE(WSDL);
  42.  try {
  43. httpTranstation.call(targetNameSpace + getHelloworld, envelope);
  44. SoapPrimitive result = (SoapPrimitive ) envelope.getResponse();
  45.  // 下面对结果进行解析,结构相似json对象
  46.  // str=(String) result.getProperty(6).toString();
  47. // int count = result.getPropertyCount();
  48. // for (int index = 0; index < count; index++) {
  49. // provinces.add(result.getProperty(index).toString());
  50. // System.out.println(result.getProperty(index).toString());
  51. // }
  52. str=result.toString();
  53. catch (IOException e) {
  54.  // TODO Auto-generated catch block
  55. e.printStackTrace();
  56. catch (XmlPullParserException e) {
  57.  // TODO Auto-generated catch block
  58. e.printStackTrace();
  59. }
  60.  return str;
  61. }
  62.  public String getFlagFromDBCust(String username,String password) {
  63. String str = "";
  64. SoapObject soapObject = newSoapObject(targetNameSpace,getLogin);
  65.  //给账号和密码加密码
  66. String encodeUsername=Base64.encode(username.getBytes());
  67. String encodePassword=Base64.encode(password.getBytes());
  68. soapObject.addProperty("username", encodeUsername);
  69. soapObject.addProperty("password",encodePassword);
  70.  //调用的方法参数与参数值(根据具体须要可选可不选)
  71. SoapSerializationEnvelope envelope = newSoapSerializationEnvelope(SoapEnvelope.VER11);
  72. envelope.dotNet = false;
  73. envelope.setOutputSoapObject(soapObject);
  74. HttpTransportSE httpTranstation=newHttpTransportSE(WSDL);
  75.  //或者AndroidHttpTransport httpTranstation = new AndroidHttpTransport(WSDL);
  76.  try {
  77. httpTranstation.call(targetNameSpace + getLogin, envelope);
  78. SoapObject result = (SoapObject ) envelope.bodyIn;//getResponse();
  79.  //
  80. str=(String) result.getProperty(0).toString();
  81.  // 也能够经过下面方式得到str
  82.  // SoapPrimitive result = (SoapPrimitive ) envelope.getResponse();
  83.  // str=result.toString();
  84.  // 直指value字符串值
  85. catch (IOException e) {
  86.  // TODO Auto-generated catch block
  87. e.printStackTrace();
  88. catch (XmlPullParserException e) {
  89.  // TODO Auto-generated catch block
  90. e.printStackTrace();
  91. }
  92.  return str;
  93. }
  94. }

 

能够看到Base64又在这里出现了,主要是为了加密码,而后传送给服务器端linux

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

而不要在后面加上?wsdl,若是加上了就错误了。程序员

 
 里面的代码。你能够下载源码进行解读。

我来提一点两种方式得到:resultweb

 

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

这两种均可以sql

而后还有数据库


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

  1. package com.net.connect.app;
  2. import Android.app.Activity;
  3. import Android.content.Intent;
  4. import Android.os.Bundle;
  5. import Android.view.View;
  6. import Android.view.View.OnClickListener;
  7. import Android.view.ViewGroup.LayoutParams;
  8. import Android.widget.Button;
  9. import Android.widget.EditText;
  10. import Android.widget.LinearLayout;
  11. import Android.widget.TextView;
  12. import Android.widget.Toast;
  13. import com.cn.blogs.ksoap.app.MyWebServiceHelper;
  14. /****
  15. * http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html
  16. *
  17. * @author mingg
  18. *
  19. */
  20. public class LoginActivity extends Activity {
  21.  /** Called when the activity is first created. */
  22. TextView txtUsername,txtPassword;
  23. EditText etUsername,etPassword;
  24. Button loginButton,exitButton;
  25.  @Override
  26.  public void onCreate(Bundle savedInstanceState) {
  27.  super.onCreate(savedInstanceState);
  28.  //setContentView(R.layout.main);
  29. constructLayout();
  30. }
  31.  private void constructLayout() {
  32. LinearLayout.LayoutParams lp = newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
  33. LinearLayout.LayoutParams controlpl = newLinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  34. LinearLayout ll = new LinearLayout(this);
  35. ll.setOrientation(LinearLayout.VERTICAL);
  36. txtUsername = new TextView(this);
  37. txtUsername.setText("账号:\t");
  38. etUsername = new EditText(this);
  39. txtPassword = new TextView(this);
  40. txtPassword.setText("密码:\t");
  41. etPassword = new EditText(this);
  42. loginButton=new Button(this);
  43. loginButton.setText("登录");
  44. loginButton.setOnClickListener(new OnClickListener() {
  45.  @Override
  46.  public void onClick(View v) {
  47.  // TODO Auto-generated method stub
  48. String userValue=etUsername.getText().toString();
  49. String passValue=etPassword.getText().toString();
  50.  if(userValue.length()==0 || passValue.length()==0){
  51. Toast.makeText(LoginActivity.this"账号和密码不能为空,请输入", Toast.LENGTH_LONG).show();
  52.  return;
  53. }
  54.  //调用自已写的webService
  55. MyWebServiceHelper webServiceHelper=newMyWebServiceHelper();
  56.  intflag=Integer.parseInt(webServiceHelper.getFlagFromDBCust(userValue,passValue));
  57. String content="";
  58.  switch (flag) {
  59.  case 1 :
  60. content="该用户不存在,请输入你的用户名";
  61. Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
  62.  break;
  63.  case 2 :
  64. content="密码输入错误,请核对";
  65. Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
  66.  break;
  67.  case 3 :
  68. content="数据库出现异常,请重试";
  69. Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
  70.  break;
  71.  case 4 :
  72. content="验证经过";
  73. Toast.makeText(LoginActivity.this, content, Toast.LENGTH_LONG).show();
  74.  try {
  75. Thread.currentThread().sleep(1000);
  76. catch (InterruptedException e) {
  77.  // TODO Auto-generated catch block
  78. e.printStackTrace();
  79. }
  80.  //转到MainActivity
  81. Intent intent=new Intent();
  82. intent.setClass(LoginActivity.this, MainActivity.class);
  83. startActivity(intent);
  84.  break;
  85.  default:
  86.  break;
  87. }
  88. }
  89. });
  90. exitButton=new Button(this);
  91. exitButton.setText("退出");
  92. exitButton.setOnClickListener(new OnClickListener() {
  93.  @Override
  94.  public void onClick(View v) {
  95.  // TODO Auto-generated method stub
  96. LoginActivity.this.finish();
  97.  //退出
  98. }
  99. });
  100. ll.addView(txtUsername, controlpl);
  101. ll.addView(etUsername, controlpl);
  102. ll.addView(txtPassword, controlpl);
  103. ll.addView(etPassword, controlpl);
  104. ll.addView(loginButton, controlpl);
  105. ll.addView(exitButton, controlpl);
  106. addContentView(ll, lp);
  107. }
  108. }

 

最终运行效果以下所示:

有点小问题,能够在开发中更正。

最终不要忘了加 internet permmition

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

相关文章
相关标签/搜索