Java实现校园网portal认证

暑假学校的网络平台升级,将Cisco全家桶换成了锐捷全家桶,同时校园网络的策略和计费也发生了显著的变化。原来的包月计费改成了校园网流量计费,同时基于认证网关分流,将部分用户划归运营商走商业网络出口,通过通过学校设备进行NAT实现两终端(学生限制)同时在线登录。

悲伤的故事在于,信息化建设处取消了原有的宿舍网络可以通过PPPoE拨号直接连接运营商网络并获取公网IP的做法,转而采用学校路由进行NAT。这样一来弊端在于连接有线网络后,无论使用运营商网络还是校园网,都必须要经过portal认证系统,而这个网页版的认证系统每次手工登录非常麻烦,而且一段时间没有流量经过会自动掉线。于是乎,通过程序自动通过portal认证变成了迫在眉睫的事情。

张文溢先使用workflow试着发出请求并取得成功后,转而采用python3写了一段脚本(跳转至github查看)以实现这些功能。然而python虽火,但毕竟不是所有的设备支持这么高级的语言(玩笑),我萌生了将其用Java重写的念头,因为分身乏术,截至发稿只完成了无线网络部分,有线之后再补充。

基本的实现原理非常简单,发送一个HTTP GET请求(其实地址可以随意,我为了省事选择直接访问认证IP),没有通过认证自然会被劫持到认证登录界面,同时返回一些必要的参数。将这些参数通过BufferedReader读取并转化为字符串(下一步提交的时候就可以直接用了)并保存下来。

之后就是向认证服务器发送账号密码并等待返回结果。无线认证网关217似乎是通过POST请求向InterFace.do的login方法发送账号、密码及必要的机器验证信息(通过Chrome开发人员工具,进入offline模式抓取即可)。程序代码通过Scanner从键盘读取账号密码,实际使用时建议直接以字符串形式在程序中写死或改成文件读取(我懒,先不改了)以实现自动化。

以下给出具体代码(截止发稿时的实现),本文不再更新,代码更新后请移步(本项目github地址)查看。

import java.io.BufferedReader;
import java.io.Console;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

public class HttpRequest {
    private final String USER_AGENT = "Mozilla/5.0";

    private String chooseISP(int choice){
        switch (choice){
            case 0:
                return "default";
            case 1:
                return "cmcc";
            case 2:
                return "unicom";
            case 3:
                return "ctcc";
            case 4:
                return "local";
            default:
                System.out.println("输入值非法,将默认连接校园网");
                return "default";
        }
    }



    // 拉取HTTP GET请求
    private void sendGet() throws Exception {
        URL urlObject = new URL("http://121.251.251.217");
        HttpURLConnection con = (HttpURLConnection) urlObject.openConnection();

        //发送方式为GET
        con.setRequestMethod("GET");
        //添加请求头
        con.setRequestProperty("User-Agent", USER_AGENT);
        System.out.println("尝试进入认证系统登录地址:");
        int responseCode = con.getResponseCode();
        System.out.println("认证系统回应:" + 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();

        //将收到的数据流转字符串
        String receivedMessage=response.toString();
        System.out.println(receivedMessage);

        //判断是否被劫持
        String authGateway = "http://121.251.251.217";

        //判断是否在线
        if("http://www.upc.edu.cn".equals(con.getURL().toString())) {
            if(receivedMessage.indexOf(authGateway) == - 1){
                System.out.println("认证系统没有返回登录地址!");
            } else {
                String identity=receivedMessage.substring(receivedMessage.indexOf(".jsp?")+5, receivedMessage.lastIndexOf("'</"));
                //System.out.println(identity);
                identity=identity.replaceAll("&","%2526");
                identity=identity.replaceAll("=","%253D");
                //System.out.println(identity);
                sendPost(identity);
            }
        } else {
            System.out.println("您已经登录,是否退出登录?(Y表示退出,其余退出程序。)");
            Scanner read=new Scanner(System.in);
            String choice=read.next();
            if (choice.equals("Y")||choice.equals("y")){
                sendPostLogout();
            } else {
                System.exit(0);
            }
        }
    }


    // HTTP POST请求(退出登录)
    private void sendPostLogout() throws Exception {
        System.out.println("尝试向认证系统发送退出登录信息。");
        String url = "http://121.251.251.217/eportal/InterFace.do?method=logout";
        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 ="method=logout";
        System.out.println(urlParameters);

        //发送Post请求
        //表示有数据要输出给服务端
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();


        System.out.println("向认证系统发送退出登录请求。" );
        int responseCode = con.getResponseCode();
//        System.out.println("Post parameters : " + urlParameters);
        System.out.println("认证系统回应: " + 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();

        //打印重定向地址
        System.out.println(con.getURL());
        //打印结果
        System.out.println(response.toString());
    }


    private void sendPost(String identity) throws Exception {
        System.out.println("尝试向认证系统发送账号密码信息。");
        String url = "http://121.251.251.217/eportal/InterFace.do?method=login";
        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");

       //数据的预处理
       Scanner read=new Scanner(System.in);
       Console console=System.console();
       System.out.print("请输入账号:");
       String number=read.next();
       System.out.print("请输入密码:");
       char[] password=console.readPassword();
       System.out.print("请选择运营商:(0、校园网;1、中国移动;2、中国联通;3、中国电信;4、校园内网;)");
       int choice=read.nextInt();
       String ISP=chooseISP(choice);


        String urlParameters ="userId="+number+"&password="+new String(password)+"&service="+ISP+"&queryString="+identity+"&operatorPwd=&operatorUserId=&validcode=";
        System.out.println(urlParameters);
        //发送Post请求
        //表示有数据要输出给服务端
        con.setDoOutput(true);

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


        System.out.println("向认证系统发送登录请求。" );
        int responseCode = con.getResponseCode();
//        System.out.println("Post parameters : " + urlParameters);
        System.out.println("认证系统回应: " + 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();

        //打印结果
        System.out.println(response.toString());
    }

    public static void main(String[] args) throws Exception {
        HttpRequest http = new HttpRequest();
        try{
            http.sendGet();
        } catch (Exception e){
            System.out.println("尝试连接UPC热点失败!");
        }
    }

}

 

分享