Android与IIS身份验证——Form验证

长平狐 发布于 2012/06/11 11:54
阅读 539
收藏 0

内容摘要

前言

设计思路 

ASP.NET服务器端

Android客户端

运行结果

         

上篇《Android与IIS身份验证——基本验证》实现了Android客户端与IIS的简单验证。而这种验证方式虽然使用起来比较简单,但是也有很多缺点。如,安全性较差,账号密码设置不灵活。让我们回顾一下ASP.NET的身份验证方式:Windows、Form和Passport。这三种验证方式中,Form身份验证方式最经常使用,因为它有很多优越性,其优点我就不一一介绍了。那么,怎样实现Android客户端与IIS的Form身份验证呢?我整理了一下,需要以下几个步骤:

  一、设计思路

  Android客户端访问IIS服务器时,当没有登陆时,ASP.NET通过Form集成验证方法会返回一个登陆页面。然后输入正确的用户名和密码,就可以进入主程序了。流程如图1.1所示。

图1.1

 

在Android客户端访问以IIS为宿主的ASP.NET服务器时,返回JSON格式来传递数据。客户端中,根据返回数据的不同而判断当前状态是否已登陆。由于Form验证是保存了Cookie,所示每次调用Http请求之前要先添加上次请求的Cookie。

二、ASP.NET服务器端

创建一个ASP.NET MVC网站项目。 

首先,由于每次请求都返回JSON格式的数据,我们编写一个Model类来承载数据。

     public   class  ResponseResult
    {
        
///   <summary>
        
///  是否已登录
        
///   </summary>
         public   bool  IsAuthenticated {  get set ; }

        
///   <summary>
        
///  是否执行成功
        
///   </summary>
         public   bool  IsSuccess {  get set ; }

        
///   <summary>
        
///  登录账号
        
///   </summary>
         public   string  Identity {  get set ; }

        
///   <summary>
        
///  执行结果
        
///   </summary>
         public   object  Result {  get set ; }
    }

 

接着,编写HomeController:

    [HandleError]
    
public   class  HomeController : Controller
    {
        [Authorize]
        
public  ActionResult Index()
        {
            
return  Json( new  ResponseResult
            {
                Result 
=   " 登陆成功 " ,
                IsAuthenticated 
=   true ,
                IsSuccess 
=   true ,
                Identity 
=   this .User.Identity.Name
            }, 
" text/html " , JsonRequestBehavior.AllowGet);
        }

        
public  ActionResult LogOn()
        {
            
return  Json( new  ResponseResult
            {
                Result 
=   " 您尚未登录 " ,
                IsSuccess 
=   true
            }, 
" text/html " , JsonRequestBehavior.AllowGet);
        }

        
public  ActionResult Register( string  account,  string  password)
        {
            
if  (account  ==   " liudong "   &&  password  ==   " 123 " )
            {
                FormsAuthentication.SetAuthCookie(account, 
false );
                
return  Json( new  ResponseResult
                {
                    Result 
=   " 登录成功 " ,
                    IsSuccess 
=   true ,
                    IsAuthenticated 
=   true ,
                    Identity 
=  account
                }, 
" text/html " , JsonRequestBehavior.AllowGet);
            }
            
else
            {
                
return  Json( new  ResponseResult
                {
                    Result 
=   " 用户名或密码错误 " ,
                }, 
" text/html " , JsonRequestBehavior.AllowGet);
            }
        }

 

Index Action为登陆认证后才能访问的Action。

LogOn Action为未登陆时跳转的Action。

Register Action为登陆Action,用户名和密码正确后就保存Form验证的Cookie。

 

然后,在Web.config中配置Form验证配置

 

< authentication  mode ="Forms" >
      
< forms  loginUrl ="~/Home/LogOn"  timeout ="2880"   />
</ authentication >


最后,配置IIS,部署ASP.NET MV网站,如图2.1所示。

 图2.1

 

三、Android客户端

  首先,编写一个调用Http请求的类。

package  ld.com.authorize;

import  java.io.BufferedReader;
import  java.io.InputStreamReader;
import  java.util.List;

import  org.apache.http.HttpEntity;
import  org.apache.http.HttpResponse;
import  org.apache.http.NameValuePair;

import  org.apache.http.client.CookieStore;
import  org.apache.http.client.entity.UrlEncodedFormEntity;
import  org.apache.http.client.methods.HttpPost;
import  org.apache.http.impl.client.AbstractHttpClient;
import  org.apache.http.impl.client.DefaultHttpClient;

import  android.util.Log;

public   abstract   class  HttpHelper {

    
private   final   static  String TAG  =   " HttpHelper " ;
    
private   final   static  String SERVER_URL  =   " http://192.168.1.104:180/Home/ " ;

    
private   static  CookieStore cookieStore;

    
public   static  String invoke(String actionName, List < NameValuePair >  params) {
        String result 
=   null ;
        
try  {
            String url 
=  SERVER_URL  +  actionName  +   " / " ;
            Log.d(TAG, 
" url is "   +  url);

            HttpPost httpPost 
=   new  HttpPost(url);
            
if  (params  !=   null   &&  params.size()  >   0 ) {
                HttpEntity entity 
=   new  UrlEncodedFormEntity(params,  " UTF-8 " );
                httpPost.setEntity(entity);
            }

            DefaultHttpClient httpClient 
=   new  DefaultHttpClient();

            
//  添加Cookie
             if  (cookieStore  !=   null ) {
                httpClient.setCookieStore(cookieStore);
            }

            HttpResponse httpResponse 
=  httpClient.execute(httpPost);

            StringBuilder builder 
=   new  StringBuilder();
            BufferedReader reader 
=   new  BufferedReader( new  InputStreamReader(
                    httpResponse.getEntity().getContent()));
            
for  (String s  =  reader.readLine(); s  !=   null ; s  =  reader.readLine()) {
                builder.append(s);
            }
            result 
=  builder.toString();
            Log.d(TAG, 
" result is (  "   +  result  +   "  ) " );

            
//  保存Cookie
            cookieStore  =  ((AbstractHttpClient) httpClient).getCookieStore();
        } 
catch  (Exception e) {
            Log.e(TAG, e.toString());
        }
        Log.d(TAG, 
" over " );
        
return  result;
    }

    
public   static  String invoke(String actionName) {
        
return  invoke(actionName,  null );
    }
}

 

注意的是,需要存储一个全局的Cookie,在每次调用前添加上去,再在调用j结束后保存它。

 

接着,添加两个布局文件:

<? xml version="1.0" encoding="utf-8" ?>
< LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"
    android:orientation
="vertical"  android:layout_width ="fill_parent"
    android:layout_height
="fill_parent" >


    
< TextView  android:text ="账号"  android:layout_width ="fill_parent"
        android:layout_height
="20dip"   />

    
< EditText  android:layout_width ="fill_parent"  android:hint ="请输入账号"
        android:layout_height
="40dip"  android:id ="@+id/edtAccount"   />

    
< TextView  android:text ="密码"  android:layout_width ="fill_parent"
        android:layout_height
="20dip"   />

    
< EditText  android:layout_width ="fill_parent"  android:hint ="请输入密码"
        android:password
="true"  android:layout_height ="40dip"  android:id ="@+id/edtPassword"   />

    
< Button  android:text ="登录"  android:layout_width ="fill_parent"
        android:layout_height
="40dip"  android:id ="@+id/btnLogon"   />
</ LinearLayout >

 

 

<? xml version="1.0" encoding="utf-8" ?>
< LinearLayout  xmlns:android ="http://schemas.android.com/apk/res/android"
    android:orientation
="vertical"  android:layout_width ="fill_parent"
    android:layout_height
="fill_parent" >

    
< Button  android:text ="调用"  android:id ="@+id/btnInvoke"
        android:layout_width
="fill_parent"  android:layout_height ="wrap_content"   />

</ LinearLayout >

 

  然后、编写登陆和主Activity

 

package  ld.com.authorize;

import  java.util.ArrayList;
import  java.util.List;

import  org.apache.http.NameValuePair;
import  org.apache.http.message.BasicNameValuePair;
import  org.json.JSONException;
import  org.json.JSONObject;

import  android.app.Activity;
import  android.app.ProgressDialog;
import  android.content.Intent;
import  android.os.AsyncTask;
import  android.os.Bundle;
import  android.util.Log;
import  android.view.View;
import  android.view.View.OnClickListener;
import  android.widget.Button;
import  android.widget.EditText;
import  android.widget.Toast;

public   class  LogonActivity  extends  Activity {

    
private   final  String TAG  =   this .getClass().getSimpleName();

    
private  EditText edtAccount;
    
private  EditText edtPassword;

    
private  Button btnLogon;

    
/**  Called when the activity is first created.  */
    @Override
    
public   void  onCreate(Bundle savedInstanceState) {
        
super .onCreate(savedInstanceState);
        setContentView(R.layout.logon);

        edtAccount 
=  (EditText)  this .findViewById(R.id.edtAccount);
        edtPassword 
=  (EditText)  this .findViewById(R.id.edtPassword);

        btnLogon 
=  (Button)  this .findViewById(R.id.btnLogon);

        setButtonOnClick();
    }

    
private   void  setButtonOnClick() {
        
this .btnLogon.setOnClickListener( new  OnClickListener() {

            @Override
            
public   void  onClick(View v) {
                
//  TODO Auto-generated method stub
                AsyncTask < Void, Void, String >  task  =   new  AsyncTask < Void, Void, String > () {

                    
private  ProgressDialog progressDialog;

                    @Override
                    
protected   void  onPostExecute(String result) {
                        
//  TODO Auto-generated method stub
                        
//  super.onPostExecute(result);
                        progressDialog.cancel();
                        Log.d(TAG, result);
                        
try  {
                            JSONObject json 
=   new  JSONObject(result);
                            String msg 
=  json.getString( " Result " );
                            
//  是否登录
                             if  (json.getBoolean( " IsSuccess " )) {
                                Toast.makeText(LogonActivity.
this , msg,
                                        Toast.LENGTH_SHORT).show();

                                
//  跳转登录Activity
                                Intent intent  =   new  Intent();
                                intent.setClass(LogonActivity.
this ,
                                        MainActivity.
class );
                                LogonActivity.
this .startActivity(intent);
                            } 
else  {
                                Toast.makeText(LogonActivity.
this , msg,
                                        Toast.LENGTH_SHORT).show();
                            }
                        } 
catch  (JSONException e) {
                            
//  TODO Auto-generated catch block
                            Log.e(TAG, e.toString());
                        }
                    }

                    @Override
                    
protected   void  onPreExecute() {
                        
//  TODO Auto-generated method stub
                         super .onPreExecute();
                        progressDialog 
=   new  ProgressDialog(LogonActivity. this );
                        progressDialog.setCancelable(
false );
                        progressDialog
                                .setProgressStyle(ProgressDialog.STYLE_SPINNER);
                        progressDialog.setTitle(
" 登录中,请稍后... " );
                        progressDialog.show();
                    }

                    @Override
                    
protected  String doInBackground(Void... arg0) {
                        
//  TODO Auto-generated method stub
                        String account  =  edtAccount.getText().toString();
                        String password 
=  edtPassword.getText().toString();
                        List
< NameValuePair >  params  =   new  ArrayList < NameValuePair > ();
                        params.add(
new  BasicNameValuePair( " account " , account));
                        params.add(
new  BasicNameValuePair( " password " , password));

                        
try  {
                            
return  HttpHelper.invoke( " Register " , params);
                        } 
catch  (Exception e) {
                            Log.e(TAG, e.toString());
                            
return   null ;
                        }
                    }
                };
                task.execute();
            }
        });
    }
}

 

 

 

package  ld.com.authorize;

import  org.json.JSONException;
import  org.json.JSONObject;

import  android.app.Activity;
import  android.app.ProgressDialog;
import  android.content.Intent;
import  android.os.AsyncTask;
import  android.os.Bundle;
import  android.util.Log;
import  android.view.View;
import  android.view.View.OnClickListener;
import  android.widget.Button;
import  android.widget.Toast;

public   class  MainActivity  extends  Activity {

    
private   final  String TAG  =   this .getClass().getSimpleName();

    
private  Button btnInvoke;

    
/**  Called when the activity is first created.  */
    @Override
    
public   void  onCreate(Bundle savedInstanceState) {
        
super .onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnInvoke 
=  (Button)  this .findViewById(R.id.btnInvoke);

        setInvokeOnClick();
    }

    
private   void  setInvokeOnClick() {
        btnInvoke.setOnClickListener(
new  OnClickListener() {

            @Override
            
public   void  onClick(View v) {
                
//  TODO Auto-generated method stub
                AsyncTask < Void, Void, String >  task  =   new  AsyncTask < Void, Void, String > () {

                    
private  ProgressDialog progressDialog;

                    @Override
                    
protected   void  onPostExecute(String result) {
                        
//  TODO Auto-generated method stub
                        
//  super.onPostExecute(result);
                        progressDialog.cancel();
                        Log.d(TAG, result);
                        
try  {
                            JSONObject json 
=   new  JSONObject(result);
                            
//  是否登录
                             if  (json.getBoolean( " IsAuthenticated " )) {
                                String msg 
=  json.getString( " Identity " +   " : "
                                        
+  json.getString( " Result " );
                                Toast.makeText(MainActivity.
this , msg,
                                        Toast.LENGTH_SHORT).show();
                            } 
else  {
                                Toast.makeText(MainActivity.
this ,
                                        json.getString(
" Result " ),
                                        Toast.LENGTH_SHORT).show();

                                
//  跳转登录Activity
                                Intent intent  =   new  Intent();
                                intent.setClass(MainActivity.
this ,
                                        LogonActivity.
class );                                
                                MainActivity.
this .startActivity(intent);
                            }
                        } 
catch  (JSONException e) {
                            
//  TODO Auto-generated catch block
                            Log.e(TAG, e.toString());
                        }
                    }

                    @Override
                    
protected   void  onPreExecute() {
                        
//  TODO Auto-generated method stub
                         super .onPreExecute();
                        progressDialog 
=   new  ProgressDialog(MainActivity. this );
                        progressDialog.setCancelable(
false );
                        progressDialog
                                .setProgressStyle(ProgressDialog.STYLE_SPINNER);
                        progressDialog.setTitle(
" 调用中,请稍后... " );
                        progressDialog.show();
                    }

                    @Override
                    
protected  String doInBackground(Void... arg0) {
                        
//  TODO Auto-generated method stub
                         try  {
                            
return  HttpHelper.invoke( " Index " );
                        } 
catch  (Exception e) {
                            Log.e(TAG, e.toString());
                            
return   null ;
                        }
                    }

                };
                task.execute();
            }
        });
    }
}

 

最后,设置访问权限:<uses-permission android:name="android.permission.INTERNET" />

四、运行结果

1.进入主MainActivity,图4.1.1所示。

图4.1.1

 

2.调用Http请求,图4.2.1所示。

图4.2.1

 

3.由于没有登陆,所以跳转到登陆Activity,图4.3.1所示。

图4.3.1

 

4.故意输入错误密码使其登陆失败,图4.4.1所示。

图4.4.1

 

5.输入正确的密码后跳转到主Activity,如图4.5.1所示。

图4.5.1

 

6.再一次调用Http请求,这次是已登陆状态,图4.6.1所示。

图4.6.1

 

 

代码下载

作者:刘冬.NET

出处:http://www.cnblogs.com/GoodHelper/archive/2011/08/19/android_iis_02.html

欢迎转载,但须保留版权。

 


原文链接:http://www.cnblogs.com/GoodHelper/archive/2011/08/19/android_iis_02.html
加载中
返回顶部
顶部