设为首页 收藏本站
查看: 839|回复: 0

[经验分享] Android与IIS身份验证——Form验证

[复制链接]

尚未签到

发表于 2015-8-12 11:29:05 | 显示全部楼层 |阅读模式
  内容摘要
    前言
    设计思路
    ASP.NET服务器端
    Android客户端
    运行结果
  
  上篇《Android与IIS身份验证——基本验证》实现了Android客户端与IIS的简单验证。而这种验证方式虽然使用起来比较简单,但是也有很多缺点。如,安全性较差,账号密码设置不灵活。让我们回顾一下ASP.NET的身份验证方式:Windows、Form和Passport。这三种验证方式中,Form身份验证方式最经常使用,因为它有很多优越性,其优点我就不一一介绍了。那么,怎样实现Android客户端与IIS的Form身份验证呢?我整理了一下,需要以下几个步骤:

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

图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所示。
DSC0001.jpg

图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所示。
DSC0002.jpg

图4.1.1

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

图4.2.1

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

图4.3.1

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

图4.4.1

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

图4.5.1

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

图4.6.1

  
  
  代码下载
  作者:刘冬.NET
  出处:http://www.iyunv.com/GoodHelper/archive/2011/08/19/android_iis_02.html
  欢迎转载,但须保留版权。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-97880-1-1.html 上篇帖子: WCF学习笔记(2)——使用IIS承载WCF服务 下篇帖子: 400 Bad Request
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表