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

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

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

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

抓包过程演示
{1} 先找到我们需要在android 端模拟登陆的教务系统网站,我这里先使用一个类似教务系统网站的网站,(是我们学校的一个网络学习中心)来实现模拟登陆,原理都是一样的,并无差别。
打开火狐浏览器的firebug 工具
打开火狐浏览器的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();}}//-->
</script>
//加密算法,贴出来一部分
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<Cookie>

                        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 看能不能 抓取到 关于登陆成功 出现的信息。 都是可以的。
演示:
登陆没有成功返回的源码(一部分)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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>Sakai</title>
        <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>
        <!-- xlogin.vm -->
        <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>

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

<!DOCTYPE html>
<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

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值