1. 程式人生 > 其它 >自動連線南郵校園網app的實現

自動連線南郵校園網app的實現

  其實連線校園網不是個難題,就是傳輸一次post請求,之前也看到有大佬用python做到電腦上的自啟動指令碼。不過由於這次想做的是app,而app最好還是用java寫,相比python會存在不少問題。

一、python指令碼的實現

  雖然要弄java,但還是藉著之前看到的python指令碼先理解一下思路。首先在校園網登入的介面用F12觀察一下連線的時候post了哪些引數:

  可以看到主要有兩個引數,DDDDD對應的是學號,形式是",0,學號和字尾",字尾如果是@cmcc就是中國移動,如果是@njxy就是中國電信,如果無後綴則是校園網;而upass即是密碼。所以我們要手動實現一次登入,只需要post這兩個引數就行,程式碼如下:

import requests
url="http://10.10.244.11:801/eportal/c=ACSetting&a=Login&wlanacip=10.255.252.150"
data={"DDDDD": ",0,學號和字尾","upass": "密碼"}
response=requests.post(url,data)

  可以說是簡單的不能再簡單……不過我們的目標肯定不是一次登入,但是要是反覆的post如果已經登入則也不太合理,參考大佬的指令碼,發現有這樣一個網址:"http://p.njupt.edu.cn:801/eportal/?c=ACSetting&a=checkScanIP&wlanuserip=",ip後加上的是get"http://p.njupt.edu.cn/"得到的v46ip的值,就能檢視到是否連線(ok/fail),如果連線還能看到自己的學號和連線的字尾,所以我們設定每隔一段時間的迴圈,先用get檢查是否連線,未連線則post資訊。程式碼如下:

import requests
import requests
import re
import time
def getIp():
    url = "http://p.njupt.edu.cn/"
    res = requests.get(url = url)
    res.encoding = 'gbk'
    results = re.search("v46ip=\'([^\']*)\'", res.text)
    ip=results.group(1)
    return ip
def checkIp(ip):
    url = "http://p.njupt.edu.cn:801/eportal/?c=ACSetting&a=checkScanIP&wlanuserip={}
".format(ip) res = requests.get(url = url) status = re.search('\"result\":\"([^\"]*)\"', res.text).group(1) if (status == 'ok'): account = re.search('\"account\":\"([^\"]*)\"', res.text).group(1) return account else: return False def login(): url="http://10.10.244.11:801/eportal/?c=ACSetting&a=Login&wlanacip=10.255.252.150" data={"DDDDD": ",0,學號@cmcc","upass": "密碼"} #修改學號和密碼 response=requests.post(url,data) return True while True: try: ip = getIp() if checkIp(ip) == False: login() except: pass time.sleep(5)

二、java指令碼的實現

  可以說思路和python一樣,但是我們需要找到這幾個函式在java中的實現方法:requests.get、requests.post、re.search

1、re.search

  用Pattern類來實現

private String re_search(String pa, String li) {
        String line = li;
        String pattern = pa;
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(line);
        if (m.find()) {
            return m.group(1);
        } else {
            return "Null";
        }
    }

2、get&post

  網上有很多指令碼,這裡我用的是java自帶的HttpsURLConnection。

private final String USER_AGENT = "Mozilla/5.0";
private String sendGet(String Url) throws Exception {

        String url = Url;

        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("GET");

        con.setRequestProperty("User-Agent", USER_AGENT);

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'GET' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        return response.toString();
    }

    private void sendPost(String Url) throws Exception {

        String url = Url;
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

        String urlParameters = "DDDDD=,0,學號@cmcc&upass=密碼"; // 修改學號密碼

        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + urlParameters);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
    }

3、完整程式碼

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HttpURLConnectionExample {

    private final String USER_AGENT = "Mozilla/5.0";

    public static void main(String[] args) throws Exception {

        HttpURLConnectionExample http = new HttpURLConnectionExample();
        String ip, status, account = "";
        int count = 0;
        while (true) {
            try {
                Thread.sleep(5 * 1000);
                ip = http.re_search("v46ip=\'([^\']*)\'", http.sendGet("http://p.njupt.edu.cn/"));
                ip = "http://p.njupt.edu.cn:801/eportal/?c=ACSetting&a=checkScanIP&wlanuserip=" + ip;
                status = http.re_search("\"result\":\"([^\"]*)\"", http.sendGet(ip));
                if (status.equals("ok")) {
                    account = http.re_search("\"account\":\"([^\"]*)\"", http.sendGet(ip));
                } else {
                    http.sendPost("http://10.10.244.11:801/eportal/?c=ACSetting&a=Login&wlanacip=10.255.252.150");
                }
                count++;
                System.out.println(count);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private String re_search(String pa, String li) {
        String line = li;
        String pattern = pa;
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(line);
        if (m.find()) {
            return m.group(1);
        } else {
            return "Null";
        }
    }

    private String sendGet(String Url) throws Exception {

        String url = Url;

        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("GET");

        con.setRequestProperty("User-Agent", USER_AGENT);

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'GET' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        return response.toString();
    }

    private void sendPost(String Url) throws Exception {

        String url = Url;
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();

        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", USER_AGENT);
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

        String urlParameters = "DDDDD=,0,學號@cmcc&upass=密碼"; // 修改學號密碼

        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + urlParameters);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
    }
}

 

三、app的實現

  然而當我用java在電腦上寫好的時候才意識到get和post在windowst和android不太一樣……android相比windows還要解決以下幾個問題:

  1、get&post

  2、面向使用者時資料的讀取和儲存

  3、下拉框(選擇移動電信還是校園網)

1、get&post

  注意的是要首先加上傳送網路請求的許可權,網上一搜有很多,除此以外注意android studio要求網路連線只能在子執行緒中進行。

       //get的用法,用String獲取get的訪問值來滿足對ip和狀態的確定
        public String sendGet(String ip){
            try {
                connection = null;
                URL url = new URL(ip);
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(3000);
                connection.setReadTimeout(3000);
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                connection.setDoOutput(false);
                connection.connect();
                responseCode = connection.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    throw new IOException("HTTP error code" + responseCode);
                }
                result = getStringByStream(connection.getInputStream());
                return result;
            }catch (IOException e) {
                e.printStackTrace();
                return "error";
            }
        }
        //post 因為這裡用不到返回值所以void就行
        public void sendPost(String ip,String pa){
            try {
                connection = null;
                URL url = new URL(ip);
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(3000);
                connection.setReadTimeout(3000);
                connection.setRequestMethod("POST");
                connection.setDoInput(true);
                connection.setDoOutput(false);
                connection.connect();
                DataOutputStream dos=new DataOutputStream(connection.getOutputStream());
                param=pa;
                dos.writeBytes(param);
                responseCode = connection.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    throw new IOException("HTTP error code" + responseCode);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        //用於返回值的處理
        private String getStringByStream(InputStream inputStream) {
            Reader reader;
            StringBuffer buffer;
            try {
                reader = new InputStreamReader(inputStream, "UTF-8");
                char[] rawBuffer = new char[512];
                buffer = new StringBuffer();
                int length;
                while ((length = reader.read(rawBuffer)) != -1) {
                    buffer.append(rawBuffer, 0, length);
                }
                return buffer.toString();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

2、資料的永久性儲存

  因為涉及需要儲存的資訊很少,所以用SharedPreferences就行。

3、下拉框

  spinner的使用,由於只是選擇和讀取所以弄個監聽器就行,不需要動態和其它的內容。

4、完整程式碼

 values.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="choice">
        <item>中國移動</item>
        <item>中國電信</item>
        <item>校園網</item>
    </string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="238dp"
        android:layout_height="107dp"
        android:text="自動連線校園網"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.514"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.62" />

    <EditText
        android:id="@+id/edt1"
        android:layout_width="261dp"
        android:layout_height="61dp"
        android:autofillHints="username"
        android:ems="10"
        android:hint="請輸入學號"
        android:inputType="textPersonName"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.44"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.134" />

    <EditText
        android:id="@+id/edt2"
        android:layout_width="261dp"
        android:layout_height="61dp"
        android:autofillHints="password"
        android:ems="10"
        android:hint="請輸入密碼"
        android:inputType="textPassword"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.433"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.225" />

    <TextView
        android:id="@+id/txv1"
        android:layout_width="227dp"
        android:layout_height="117dp"
        android:text="Test"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.538"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.884" />

    <TextView
        android:id="@+id/txv2"
        android:layout_width="228dp"
        android:layout_height="50dp"
        android:text="Test"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.54"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txv1"
        app:layout_constraintVertical_bias="0.0" />

    <Button
        android:id="@+id/btn"
        android:layout_width="121dp"
        android:layout_height="66dp"
        android:text="修改"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.944"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.407" />

    <Spinner
        android:id="@+id/spinner"
        android:entries="@array/choice"
        android:layout_width="262dp"
        android:layout_height="39dp"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.436"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/edt2"
        app:layout_constraintVertical_bias="0.0" />

</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.network;

import androidx.appcompat.app.AppCompatActivity;
import java.io.*;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.app.Activity;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Toast;

import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.net.URLConnection;
public class MainActivity extends AppCompatActivity {

    Person p1=new Person();
    String pa ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button2 = findViewById(R.id.button);
        Button button1 = findViewById(R.id.btn);
        button1.setOnClickListener(new BtnClickListener());
        button2.setOnClickListener(new BtnClickListener());
        Spinner cho=findViewById(R.id.spinner);
        cho.setOnItemSelectedListener(new ProvOnItemSelectedListener());
    }
    //下拉框的監聽
    private class  ProvOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
        @Override
        public void onItemSelected(AdapterView<?> adapter,View view,int position,long id) {
            String sInfo=adapter.getItemAtPosition(position).toString();
            if(sInfo.equals("中國移動")) p1.setType("@cmcc");
            if(sInfo.equals("中國電信")) p1.setType("@njxy");
            if(sInfo.equals("校園網")) p1.setType("校園網");
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
            String sInfo="null";
        }
    }
    // 按鈕的監聽
    class BtnClickListener implements View.OnClickListener {
        //學號和密碼
        String name;
        String code;
        @Override
        public void onClick(View v) {
            EditText txtName=findViewById(R.id.edt1);
            EditText txtCode=findViewById(R.id.edt2);
            Integer i=v.getId();
            //修改被點選時
            if(i.equals(R.id.btn)){
                //獲取輸入框的值
                name = txtName.getText().toString().trim();
                code = txtCode.getText().toString().trim();
                //資料的永久儲存
                SharedPreferences.Editor editor = getSharedPreferences("lock", MODE_PRIVATE ).edit();
                editor.putString("name", name);
                editor.putString("code", code);
                editor.putString("type", p1.getType());
                editor.apply();
                //提示資訊
                Toast.makeText(getApplicationContext(), "設定成功", Toast.LENGTH_LONG).show();
            }
            //連線校園網被點選時
            if(i.equals(R.id.button)) {
                //從SharedPreferences中讀取資料
                SharedPreferences read = getSharedPreferences("lock", MODE_PRIVATE );
                p1.set(read.getString("name", ""), read.getString("code", ""),read.getString("type",""));
                //校園網的時候引數沒有後綴,修改無法實現,怎麼辦?修改就直接改成校園網,加個判斷就行
                if(p1.getType().equals("校園網")) {
                    pa = "DDDDD=,0," + p1.getId() + "&upass=" + p1.getPassword();
                }else{
                    pa = "DDDDD=,0," + p1.getId() + p1.getType() + "&upass=" + p1.getPassword();
                }
                //提示資訊
                Toast.makeText(getApplicationContext(), pa, Toast.LENGTH_LONG).show();
                //開啟子執行緒實現網路訪問
                new Thread(runnable).start();
            }
        }
    }
    //用類方便修改學號密碼以及型別,其實這裡不用也挺方便的
    public class Person{
        String id;
        String password;
        String type="@cmcc";
        public Person(){
        }
        public void set(String i,String p,String t){
            id=i;
            password=p;
            type=t;
        }
        public void setType(String t){
            type=t;
        }
        public String getId(){
            return id;
        }
        public String getPassword(){
            return password;
        }
        public String getType(){
            return type;
        }
    }
    //子執行緒
    Runnable runnable = new Runnable() {
        String ip,status,account,text;
        int responseCode,count=0;
        HttpURLConnection connection ;
        String result,param;
        String line,pattern;


        @Override
        public void run() {
            TextView text1 = findViewById(R.id.txv1);
            TextView text2 = findViewById(R.id.txv2);
            text1.setText("請稍等…………");
            text2.setText("大約有五秒間隔");
            count=0;
            while(true){
                try {
                    Thread.sleep(5000);
                    count++;
                    //get改網址讀取ip
                    text = sendGet("http://p.njupt.edu.cn/");
                    ip = re_search("v46ip='([^']*)'", text);
                    //這個ip可以訪問聯網的狀態
                    ip = "http://p.njupt.edu.cn:801/eportal/?c=ACSetting&a=checkScanIP&wlanuserip=" + ip;
                    text = sendGet(ip);
                    status = re_search("\"result\":\"([^\"]*)\"", text);
                    text1.setText(status+"\n"+ip);
                    //第一次可能存在該ip已經對應有聯網的狀態了,所以必須post
                    if(count==1) {
                        ip = "http://10.10.244.11:801/eportal/?c=ACSetting&a=Login&wlanacip=10.255.252.150";
                        sendPost(ip, pa);
                    } else if (status.equals("ok")&&count!=1) {
                        //ok的時候可以獲取到學號,其實這裡什麼也不需要做
                        account = re_search("\"account\":\"([^\"]*)\"", text);
                        text2.setText(account);
                    } else {
                        //fail或者其它情況傳送post請求
                        ip = "http://10.10.244.11:801/eportal/?c=ACSetting&a=Login&wlanacip=10.255.252.150";
                        sendPost(ip, pa);
                    }
                    //count做個計數,沒有也行,但既然有計數那就也考慮一下溢位上限的情況
                    if(count<0) {
                        count = 2;
                    }
                    text2.setText(account+"  "+count);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //get的用法,用String獲取get的訪問值來滿足對ip和狀態的確定
        public String sendGet(String ip){
            try {
                connection = null;
                URL url = new URL(ip);
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(3000);
                connection.setReadTimeout(3000);
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                connection.setDoOutput(false);
                connection.connect();
                responseCode = connection.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    throw new IOException("HTTP error code" + responseCode);
                }
                result = getStringByStream(connection.getInputStream());
                return result;
            }catch (IOException e) {
                e.printStackTrace();
                return "error";
            }
        }
        //post 因為這裡用不到返回值所以void就行
        public void sendPost(String ip,String pa){
            try {
                connection = null;
                URL url = new URL(ip);
                connection = (HttpURLConnection) url.openConnection();
                connection.setConnectTimeout(3000);
                connection.setReadTimeout(3000);
                connection.setRequestMethod("POST");
                connection.setDoInput(true);
                connection.setDoOutput(false);
                connection.connect();
                DataOutputStream dos=new DataOutputStream(connection.getOutputStream());
                param=pa;
                dos.writeBytes(param);
                responseCode = connection.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    throw new IOException("HTTP error code" + responseCode);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        //用於返回值的處理
        private String getStringByStream(InputStream inputStream) {
            Reader reader;
            StringBuffer buffer;
            try {
                reader = new InputStreamReader(inputStream, "UTF-8");
                char[] rawBuffer = new char[512];
                buffer = new StringBuffer();
                int length;
                while ((length = reader.read(rawBuffer)) != -1) {
                    buffer.append(rawBuffer, 0, length);
                }
                return buffer.toString();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        //模擬python中的re.search
        private String re_search(String pat, String li) {
                line = li;
                pattern = pat;
                Pattern r = Pattern.compile(pattern);
                Matcher m = r.matcher(line);
                if (m.find()) {
                    return m.group(1);
                } else {
                    return "null";
                }
        }
        };

}

  以上,不過也就只有在南郵能用,主要是寫一下思路。