Preface

As is well known, many universities’ wireless networks are password-free, replaced instead by a web authentication (portal) method. Users can easily access the network by entering their usernames and passwords, as shown in the figure below (image source: internet):

src=http___www.sundray.com.cn_ueditor_net_upload_image_20160718_6360440473834486725969911.png&refer=http___www.sundray.com

However, this authentication method has a drawback: frequent disconnections. Manually logging in via the web portal using a username and password is cumbersome, which led to the creation of this software for automatic campus network login.

Principle Explanation

Web authentication is essentially an HTML page used to display to users for entering usernames and passwords. The user’s input is sent to the backend server via a POST request for verification. If the verification passes, access is granted; otherwise, access is denied, similar to most website login mechanisms.

Introduction to the Campus Network Automatic Login Program

1. Program Flow

image-20221025185128606

2. Technologies Used

  • GET Request – Used to determine if the computer can access the internet.
  • POST Request – Used to send data to the authentication server.
  • Swing Window – Used to display prompt messages.
  • Properties Configuration File – Used to store user information.
  • Socket Communication – Tests connectivity with the authentication server.
  • Multithreading – Ensures the window does not appear frozen.
  • URL Splitting – Extracts information from the authentication URL.

I. Testing Internet Connectivity with GET Request

This is a built-in Java library that can be used directly.

import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPGet {
    public static int testWsdlConnection(String address) throws Exception {
        int status = 404;
        try {
            URL urlObj = new URL(address);
            HttpURLConnection oc = (HttpURLConnection) urlObj.openConnection();
            oc.setUseCaches(false);
            oc.setConnectTimeout(3000);
            status = oc.getResponseCode();
            if (200 == status) {
                // 200 indicates a successful connection to the address.
                return status;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        return status;
    }
}

II. Sending POST Requests

This requires the httpclient library, which needs to be added to Maven.

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.3</version>
</dependency>

Basic Usage

Define a sendPOST function, which can be called directly when needed.

import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HTTPPost {
    /**
     *
     * Send a request
     * @param url The URL to send
     * @param headerMap Request header parameter collection key parameter name, value as parameter value
     * @param bodyMap Request parameter collection key parameter name, value as parameter value
     */
    public static String sendPost(String url, Map<String,String> headerMap, Map<String,String> bodyMap){
        // Create a POST request object
        HttpPost post = new HttpPost(url);
        try {
            // Create a parameter collection
            List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
            // Add parameters
            if (bodyMap!=null){
                for (String str:bodyMap.keySet()) {
                    list.add(new BasicNameValuePair(str, bodyMap.get(str)));
                }
            }
            // Put the parameters into the request object, specifying the format for POST request parameters
            post.setEntity(new UrlEncodedFormEntity(list));
            if (headerMap!=null){
                for (String str:headerMap.keySet()
                ) {
                    post.addHeader(str,headerMap.get(str));
                }
            }
            CloseableHttpClient client = HttpClients.createDefault();
            // Execute the request and obtain the response
            CloseableHttpResponse response = client.execute(post);
            // Get the returned entity object
            HttpEntity entity = response.getEntity();
            // Return content
            return EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e1) {
            e1.printStackTrace();
            return "";
        }
    }
}

Campus Network Login

Based on the sendPOST function, we need to prepare the URL, headers, and body. These parameters are easily obtainable from the browser’s Developer Tools.

Browser F12

If the browser’s developer tools do not meet your needs, it is recommended to use a professional packet sniffer.

Packet Sniffing

After obtaining everything, we store it in a string and then convert it into the form of Map<String,String>. Here, we need to use the fastjson component developed by Alibaba, which also needs to be added to Maven.

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.66</version>
</dependency>

The complete code is as follows:

String header = "{\"Cache-Control\": \"max-age=0\", \"Upgrade-Insecure-Requests\": \"1\", \"Origin\": \"\", \"Content-Type\": \"application/x-www-form-urlencoded\", \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44\", \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\", \"Referer\": \"\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept-Language\": \"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6\", \"Connection\": \"close\"}";
Map<String, String> mapheader = JSONObject.parseObject(header, new TypeReference<Map<String, String>>(){});
Map<String, String> params = new HashMap<String, String>(){{
    put("R1", "0");
}};
// Add username and password to params
params.put("DDDDD", name);
params.put("upass", b64.decode2(passwd));
String htmlStr = HTTPPost.sendPost(Path.trim(), mapheader, params);

Java Web Crawler

After sending the POST request, we need to determine if the login was successful. Since our university’s login response is not a JSON list but an HTML file, the most significant feature is the page title: Authentication Successful Page. We need to use this title to determine if the login was successful, so we need to use Java’s web crawling capabilities.

Document doc = Jsoup.parse(htmlStr);
String e_title = doc.title();
return Objects.equals(e_title, "认证成功页");

There is a major pitfall here: string comparison using e_title == "Authentication Successful Page" does not work no matter how hard you try. Later, after asking our teacher, we learned about Java’s string comparison methods.

WeChat Screenshot_20221025194613

III. Reading Configuration Files

Here, we use Java’s properties configuration file, where both the username and password are stored.

WeChat Screenshot_20221025143007

Reading

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class ReadPropertise {
    private static Properties properties = new Properties();
    private static BufferedInputStream in;
    public static void Readin() throws Exception{
        try {
            in = new BufferedInputStream(new FileInputStream("c.properties"));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        try {
            properties.load(in);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
	// Read the username and password values
    public static List getUser(){
        String name = properties.getProperty("name");
        String passwd = properties.getProperty("password");
        List map = new ArrayList();
        map.add(name);
        map.add(passwd);
        return map;
    }
}

Writing

Retrieve data from the Swing window’s input fields and write it to the properties file.

img

Properties properties = new Properties();
properties.setProperty("name", name);
properties.setProperty("password", passwd);
try {
     properties.store(new FileWriter("c.properties"), null);
} catch (IOException ex) {
     throw new RuntimeException(ex);
}

Swing Window Framework

Swing is a windowing module in Java, also built-in, and will be explained using comments below.

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

public class LoginSwing {
    
    public void placeComponents() {
        // Create a window
		JFrame frame = new JFrame("Login");//Login is the window title
        // Set window size
        frame.setSize(350, 200);
        // Window style
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Create a panel
        JPanel panel = new JPanel();

		// Username prompt
        JLabel userLabel = new JLabel("Username:");
		// Set label position absolutely
        userLabel.setBounds(10, 20, 60, 25);
        // Add label to panel
        panel.add(userLabel);
		
        // Username input field
		JTextField userText = new JTextField(20);
        userText.setBounds(65, 20, 165, 25);
        panel.add(userText);

		// Password prompt
        JLabel passwordLabel = new JLabel("Password:");
        passwordLabel.setBounds(10, 50, 60, 25);
        panel.add(passwordLabel);

        // Password input field, hides input content
		JPasswordField passwordText = new JPasswordField(20);
        passwordText.setBounds(65, 50, 165, 25);
        panel.add(passwordText);

        // Create a label for the address
        JLabel addLabel = new JLabel("Address:");
        addLabel.setBounds(10, 80, 60, 25);
        panel.add(addLabel);

        // Create an address input field
        JTextField addText = new JTextField(20);
        addText.setBounds(65, 80, 165, 25);
        panel.add(addText);

        // Create a label for prompt messages
        JLabel noticeLabel = new JLabel();
        noticeLabel.setForeground(Color.red);
        noticeLabel.setBounds(95, 110, 90, 25);
        panel.add(noticeLabel);

        // Create a login button
        JButton loginButton = new JButton("Login");
        loginButton.setBounds(10, 110, 80, 25);
        panel.add(loginButton);
		// Button click event
        loginButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String name = userText.getText().trim();//Retrieve content from input field, trim removes spaces
                String passwd = String.valueOf(passwordText.getPassword());
                String host = addText.getText().trim();
                if ("".equals(name)) {
                    noticeLabel.setText("Please enter a username!");
                } else if ("".equals(passwd)) {
                    noticeLabel.setText("Please enter a password!");
                } else if ("".equals(host)) {
                    noticeLabel.setText("Please enter an address!");
                } else {
                    // Execute statements
                    // Modify label content
                    noticeLabel.setText("Login successful");
                    // Close window
                    frame.dispose();
                }
            }
        });
        // Add panel to window
        frame.add(panel);
        frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
        panel.setLayout(null);
        // Display window
        frame.setVisible(true);
    }
}

Socket Testing

Before logging in, we should check if the campus network’s authentication server is working. This also uses Java’s built-in library.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class SocketTest {
    // Determine if IP and port are connectable
    public static boolean isHostConnectable(String host, int port) {
        Socket socket = new Socket();
        try {
            socket.connect(new InetSocketAddress(host, port));
        } catch (IOException e) {
            //e.printStackTrace();
            return false;
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                //e.printStackTrace();
            }
        }
        return true;
    }
}

Java Multithreading Usage

Basic Usage

new Thread(new Runnable() {
	@Override
	public void run() {
	}
}.start()

Example: Sleep Sorting

public class Main {
    public static void main(String[] args) {
        int[] nums = new int[]{235, 233, 110, 789, 5, 0, 1};
        for (int item : nums) {
            new Thread(() -> {
                try {
                    Thread.sleep(item);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(item);
            }).start();
        }
    }
}

Do not use this in production environments. This code is so complex that it’s hard to think of without a brain hemorrhage. The problems exposed by sleep sorting are also obvious:

  1. It cannot sleep for negative numbers.
  2. There is an error between similar numbers.
  3. If you give it a very large number to sleep, it might not even be cured from a brain hemorrhage.

Download

Download link 1:

Link: https://pan.baidu.com/s/1TnHwBci5RD_67hNRG8XSUQ

Extract code: afi7

Source code download