针对 android端模拟教务系统登陆,主要针对抓包过程,post,get请求,和解析网页和cookie(一)

2016年8月31日00:03:40
本人android新手,就读于安阳师范学院,最近在做教务系统登陆的案例,也是在拜读了网上很多做过类似案例的博客,发表一下自己的一点见解。

  • 【0】使用了相关类 HttpClient Jsoup(jsoup这个需要自己下载jar包)
  • 【1】我使用的是 火狐浏览器的 firebug 工具进行的抓包(在火狐的插件里可以下载)

抓包过程演示
{1} 先找到我们需要在android 端模拟登陆的教务系统网站,我这里先使用一个类似教务系统网站的网站,(是我们学校的一个网络学习中心)来实现模拟登陆,原理都是一样的,并无差别。
打开火狐浏览器的firebug 工具

找到登陆界面,填写我们的账号 和 密码
(注意事项:在firebug界面的 ”保持“ 选项要选中,这样才能看懂到 post请求)

登陆成功后,我们来看第一条,标识有 post 状态 为(302 或者 200)

在这个里面 分别有 头信息 , post 数据,cookies 这三个是比较重要的,
头信息中可以知道
Cookie JSESSIONID=3478af40-368a-4f91-a467-01ec789f1fd2.Test01 (这个主要用于标识我们的身份,就是让服务器知道你是 张三,而不是李四,这个很重要。)
Referer
Referer http://202.196.240.54/portal/relogin (这个就是我们需要在android 端使用到的进行post登陆网址)

下面来看 post 的相关数据项(我把密码涂掉了)
这个是很简单的没有太多参数
eid 对应就是 账号
pw 对应就是 密码
submit 对应是登陆(这只是个参数,没有卵用,而且它需要 url编码 ,可以看见在下面的 源代码中 是这样的:%E7%99%BB++%E5%BD%95 到时候在代码中实现 是这样的 : URLEncoder.encode(“登陆”, “gbk”))

这些数据项我们都要用到,至少针对这个 post 是这样的,但是有些数据项会很多,在android 模拟登陆的时候我还不太清楚是不是有些不用提交。

来看 cookies 说白了就是我们在 头信息中 cookie(3478af40-368a-4f91-a467-01ec789f1fd2.Test01 ) 的值,我就不上图了

【分割线***********************************************************
针对上面的post 中数据项少,我把正常情况的数据项贴出来,并并做出一些解释和我想询问的问题:


这个 是我们学校教务系统登陆后的 post 数据项
在这里我解释一下我怎么没用我们学校的教务系统来写这个.
我们学校使用的教务系统是青果的,我在分析这个 post数据项的时候 ,发现
txt_pewerwedsdfsdff
txt_sdertfgsadscxcadsads
这两个都是空值,这两个我看过网页源码 一个是 密码 一个是 验证码,可是为什么是空值,答案就在 上面的这两个参数
dsdsdsdsdxcxdfgfg
fgfggfdgtyuuyyuuckjg
第一个是密码,第二个是验证码,这个是因为它进行了 md5 加密,将密码 和 验证码 加密了,而且我在看网页源码的时候,找到了 加密过程 和 加密算法,

unction chkpwd(obj)  // 加密密码的{  if(obj.value!='')  {     var s=md5(document.all.txt_asmcdefsddsd.value+md5(obj.value).substring(0,30).toUpperCase()+'10479').substring(0,30).toUpperCase();    document.all.dsdsdsdsdxcxdfgfg.value=s;} else { document.all.dsdsdsdsdxcxdfgfg.value=obj.value;} } // 加密验证码的  function chkyzm(obj) {  if(obj.value!='') {   var s=md5(md5(obj.value.toUpperCase()).substring(0,30).toUpperCase()+'10479').substring(0,30).toUpperCase();   document.all.fgfggfdgtyuuyyuuckjg.value=s;} else {    document.all.fgfggfdgtyuuyyuuckjg.value=obj.value.toUpperCase();}}//-->
//加密算法,贴出来一部分unction md5js(pass, code, uin) {var I = hexchar2bin(md5(pass));var H = md5(I + uin);var G = md5(H + code.toUpperCase());return G}var hexcase = 1;var b64pad = "";var chrsz = 8;var mode = 32;function md5(A) {return hex_md5(A)}function hex_md5(A) {return binl2hex(core_md5(str2binl(A), A.length * chrsz))}function str_md5(A) {return binl2str(core_md5(str2binl(A), A.length * chrsz))}function hex_hmac_md5(A, B) {return binl2hex(core_hmac_md5(A, B))}

所以我在android 实现登陆我们学校的教务系统的时候,就出现了问题,因为我在发送参数的 只能发送 post 请求那样写的 参数,所以我自己要将加密过程实现,或者还有其它的方法,但我没想到。
出现这个好像是只要在 青果的教务系统 上, 正方的教务系统 应该是没有加密。

如果那位大神知道怎么弄,需要可以解决一下。
分割线***********************************************

好了,我们言归正传,对登陆过程的抓包,基本就是这些了。
下面我们将利用到我们得到的东西,在android 端实现这个过程,我们先明确一下过程.
【0】写好我们的登陆界面,并加上网络访问权限
【1】拿到我们需要登陆的网址 http://202.196.240.54/portal/relogin
【2】使用 HttpClient 相关类来 实现登陆过程
【3】设置我们需要参数 (post的数据项)
【4】判断访问是否成功 (==200)
【5】拿到返回的 cookies
【6】拿到响应的网页源码,并且使用 jsoup 解析,这样就拿到我们需要的信息。
【7】将获取的信息,在控件上显示出来。

代码展示 :
【0】登陆界面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.aynu.dengluanli.MainActivity" >    <TextView        android:id="@+id/id"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="账号" />    <EditText        android:id="@+id/id_ed"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/pwd"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="密码" />    <EditText        android:id="@+id/pwd_ed"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <Button        android:id="@+id/tijiao"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="onclick"        android:text="登陆" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <TextView            android:id="@+id/id_text_infor"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="144803085"            android:textSize="30sp" />    LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <TextView            android:id="@+id/name_text_infor"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="***"            android:textSize="30sp" />    LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <TextView            android:id="@+id/sj_text_infor"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="2016年8月30日"            android:textSize="20sp" />    LinearLayout>LinearLayout>


下面的三个 textview 等会我们会拿到我们的个人信息,然后更新上去。

网络访问权限 : android.permission.INTERNET (因为我们需要访问网络)

【1】登陆网站的过程 (其中有些我写有注解)

// 提交按钮的点击事件    public void onclick(View v) {        new Thread(new Runnable() { // 耗时操作必须使用子线程            @Override            public void run() {                try {                String un = username.getText().toString().trim(); // 获取填写的 用户名                String pwd = password.getText().toString().trim(); // 获取填写的 密码                // 【1】进行post 请求 使用httpclient                client = new DefaultHttpClient();//【1.1】 实例化的httpclient 对象                // 【1.2】进行post请求                HttpPost httpPost = new HttpPost(postURL);                // postURL  就是我们获得网址                // 【1.3】设置要进行 post请求的参数                List<NameValuePair> list = new ArrayList<NameValuePair>();                list.add(new BasicNameValuePair("eid", un));                list.add(new BasicNameValuePair("pw", pwd));                list.add(new BasicNameValuePair("submit", URLEncoder.encode("登陆", "gbk")));  // 上面出现的一个乱码部分,使用了url编码                    // 提交表单信息                    httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));                    // 响应请求                    HttpResponse httpResponse = client.execute(httpPost);                    // 判断状态码 如果为 200 则要检查表单 如果为 302 继续                    // //有的,其实我通过HttpWatch抓取的返回值就是302,只不过创建HttpClient时用的new                    // DefaultHttpClient()                    // 这个函数会直接跳转200,如果你用了DefaultHttpClient还是返回302的话,你可以 location                    // = response.getFirstHeader("Location").getValue()                    // location中有你想要的网址,然后再重新Post新网址就好                    if (httpResponse.getStatusLine().getStatusCode() == 200) {                         // 获取 cookie                        cookies = client.getCookieStore().getCookies(); // 拿到的cookies 返回形式是 List                        HttpEntity entity = httpResponse.getEntity();                        String main_html = EntityUtils.toString(entity);  // 这个就是响应的网页源码                        IsLoginSuccessful(main_html); // 这个方法是jsoup 解析的方法,可以先不看                    } else {                        System.out.println("    请求失败");                    }                } catch (Exception e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }).start();    }

在这里说一下我的一些看法,
(1)你获得到 cookie 后,可以跟 咱们之前在网站上 获取到的 cookie 进行对比,但是 会出现两种情况,一种是 cookie 整好比对上,并且每次都不会变化, 还有一种是 cookie 都会变化(当然这个是 账号 密码 都正确,不是账号密码不正确出现的),但是 这个不影响你的操作, 我还不清楚这个是怎么回事, 但是这个在你 携带 cookie 进行请求的时候,不会出现问题,你只需要将你拿到的 cookie 设置进去就行。
(1)你怎么才能知道你 登陆成功了么,在我们做的判断的地方
if (httpResponse.getStatusLine().getStatusCode() == 200) 这个只是请求是否成功的标志,并不是你登陆 是否成功的标志,你要查看你返回的 网页源码,通过看这个 你就知道你 是否登陆 成功了。
或者你通过 jsoup 看能不能 抓取到 关于登陆成功 出现的信息。 都是可以的。
演示:
登陆没有成功返回的源码(一部分)

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">    <head>        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />         <link href="/library/skin/tool_base.css" type="text/css" rel="stylesheet" media="all" />        <link href="/library/skin/neo-bupt-blue/tool.css" type="text/css" rel="stylesheet" media="all" />        <meta http-equiv="Content-Style-Type" content="text/css" />        <title>Sakaititle>        <script type="text/javascript" src="/library/js/jquery/1.4.2/jquery-1.4.2.min.js">script>        <script type="text/javascript" language="JavaScript" src="/library/js/headscripts.js">script>        <meta name="viewport" content="width=device-width"/>            head>    <body onload="if ((document.getElementById('pw').passwordfocus != true)) document.getElementById('eid').focus() ;parent.updCourier(doubleDeep, ignoreCourier);">        <script type="text/javascript" language="JavaScript">            focus_path = ["eid"];        script>                <table class="login" cellpadding="0" cellspacing="0" border="0">        <tr>            <th colspan="2">登  录th>        tr>        <tr>            <td class="logo">td>            <td class="form">                <form method="post" action="http://202.196.240.54/portal/relogin" enctype="application/x-www-form-urlencoded">                                    <div class="alertMessage">登录信息不正确div>                                    <table border="0" class="loginform">                    <tr>                        <td><label for="eid">用户名label>td>                        <td><input name="eid" id="eid" value="144803085" type="text" size="15"/>td>                    tr>

登陆成功返回的源码(一部分)

<html lang="zh-CN">   <head>    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />    <meta http-equiv="Content-Style-Type" content="text/css" />    <meta http-equiv="Content-Language" content="zh-CN" /><script type="text/javascript">    var portal = {        "chat": {            "enabled": false,            "pollInterval": 5000,            "video": {},            "translations": {                "server_unavailable": "It looks like the chat server is unavailable. Check your network connection.",                "server_error_send" : "Failed to send message. Reason: ",                "server_error_send_error": "Error: "            },        },        "loggedIn": true,        "portalPath": "http://202.196.240.54/portal",        "loggedOutUrl": "http://202.196.240.54/portal",        "siteId": "~144803085",        "siteTitle": "我的工作空间",        "shortDescription": "",        "locale": "zh-CN",        "user": {            "id": "144803085",            "eid": "144803085"        },

(3) 我们获取到的 cookie存放在 List 中,所以写一个方法,将 cookie的值读出来,方便我们在接下来 携带 cookie 请求时使用。

/**     * 解析保存到的 cookies     * @return cookies 值     */    public String parseCookie(){        // 判断cookies 是不是为空        if (cookies.isEmpty()) {            System.out.println("cookies为空");        }else { // cookies 不为空,就从list中取出cookies 的value 值            for (int i = 0; i < cookies.size(); i++) {                Cookie cookie = cookies.get(i);                System.out.println(cookies.get(i).getName()+"===="+cookies.get(i).getValue());                cookies_value = cookies.get(i).getValue(); //拿到我们的 cookie 类型为 string            }        }        return cookies_value;    }

返回的结果 : 2474bce1-9ce1-4618-97de-dc861c48dcf6.Test01

这样基本上,登陆过程就结束了。
先写到这里,明天继续写。

更多相关文章

  1. 完成登陆实例
  2. android调用asp.net webservice,返回json结构
  3. Android(安卓)微信登陆
  4. Android简单登陆页面
  5. Android客户端+mysql+springmvc服务器端实现登陆的小案例
  6. Android之BaseAdapter的使用
  7. Android(安卓)自带语音识别功能
  8. 对OAuth2认证的小结【Android】
  9. Android(安卓)开发(二)登陆界面

随机推荐

  1. Android实时获得周围wifi信息(SSID,强度等)
  2. Android热点回顾第六期
  3. Android(安卓)Studio学习1——初始Androi
  4. Android(安卓)控件布局常用属性
  5. 动画Animation ,一点点
  6. android 去掉标题栏 禁止横竖屏 保持全屏
  7. android:gravity与android:layout_gravit
  8. ❤️Android(安卓)从源码解读 Apk 的安装过
  9. Android:GridView+AbsoluteLayout作一个
  10. android startService onStartCommand 多