利用java/android 模拟网页表单提交。可用于爬虫和wif登录器制作

18 篇文章 0 订阅

学校的wifi登录页又改了。。之前做的wifi登录器没用了。按理说是没换什么接口啊什么的。可是就是不能用了。


我之前做的登录器倒也是省事。直接把填好信息的网页存本地一个。到时候直接用webview加载 一下就ok了。简单粗暴。不好的地方就是不能及时的获取返回值。虽然我用webview和网页里面的js代码做了交互,不过可能是因为执行顺序的问题导致不能及时的取得类似于密码错误 和用户名不存在这样的消息。所以这次打算时隔半年。用学到的东西再重新写一遍


前一个暑假学会了爬虫,爬虫说简单点实际上就是一般只能抓你看到的网页的内容。优点就是它可以非常快,非常准。所以当时要分析网页里边的各种结构。当时抓取的是人人网的东西,但是它用的是异步加载,一个网页实际上是先加载大体框架再逐步的去加载子网页的。这就对当时的抓取信息造成了一定的不方便,因为之前看过浏览器确实是有开发者这个选项的。就随便去试了一下。然后比较了各浏览器的开发者功能之后发现firefox无论从执行速度 还是从开发的功能上都非常厉害。我在研究网页的时候safari经常假死,firefox就非常的快。


以百度为例。想要模拟表单提交,主要是看参数这一栏,然后用namevaluepair去写入到请求中去,再去执行。我们都知道请求分为两种方法。一个是get一个是post。所以只要弄清楚这几个。然后对比一下网页。只要基本上一致就没有问题。之前在创业的时候认识了个做爬虫方面的大神,他告诉我说这种测试要用java去执行一下试试才能知道具体卡在哪,才方便去找问题。比如我的问题是卡在httpclient.executemethod这行中了。然后他告诉我就是参数写的不对。后来才发现的应该是https请求。

这次还是弄了好久。主要遇到的问题就是jar包上的选择。二是wifi登录用的是https的表单,之前都是http方式进行的测试。找了半天才发现还多了一个s呢。talk is cheap .show code。另外commons.httpclient那几个包建议用最新的。百度第一个就是。现在的版本是4.5.3.下好了之后里面不光是只有这一个包。其它的辅助包也要。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class Test {
	public static void main(String[] args) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("username", "2012011294");
		params.put("password", "*******");
		params.put("buttonClicked", "4");
		sendSSLPostRequest("https://1.1.1.1/login.html", params);
		// logout();
	}

	//
	// public static void Login() {
	// HttpClient httpClient = new HttpClient();
	// String url = "http://1.1.1.1/login.html";
	// PostMethod postMethod = new PostMethod(url);
	// postMethod
	// .addRequestHeader(new Header(
	// "User-Agent",
	// "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:33.0) Gecko/20100101 Firefox/33.0"));
	// postMethod.addRequestHeader(new Header("Referer",
	// "http://1.1.1.1/login.html"));
	// postMethod
	// .addRequestHeader(new Header("Accept",
	// "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
	// postMethod.addRequestHeader(new Header("Accept-Encoding",
	// "gzip, deflate"));
	// postMethod.addRequestHeader(new Header("Connection", "keep-alive"));
	// postMethod.addRequestHeader(new Header("Host", "1.1.1.1"));
	//
	// postMethod.addParameter("Content-Type",
	// "application/x-www-form-urlencoded");
	//
	// // 填入各个表单域的值
	// NameValuePair[] data = { new NameValuePair("username", "2012011294"),
	// new NameValuePair("password", "******"),
	// new NameValuePair("buttonClicked", "4") };
	// // 将表单的值放入postMethod中
	// postMethod.setRequestBody(data);
	// // 执行postMethod
	// int statusCode = 0;
	// try {
	// statusCode = httpClient.executeMethod(postMethod);
	// } catch (HttpException e) {
	// e.printStackTrace();
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// // HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发
	// // 301或者302
	// if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY
	// || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
	// // 从头中取出转向的地址
	// Header locationHeader = postMethod.getResponseHeader("location");
	// String location = null;
	// if (locationHeader != null) {
	// location = locationHeader.getValue();
	// System.out.println("diandianLogin:" + location);
	// } else {
	// System.err.println("Location field value is null.");
	// }
	// return;
	// } else {
	// System.out.println(postMethod.getStatusLine());
	// String str = "";
	// try {
	// str = postMethod.getResponseBodyAsString();
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// System.out.println(str);
	// }
	// postMethod.releaseConnection();
	// return;
	// }
	//
	public static void logout() {
		org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient();
		String url = "http://1.1.1.1/logout.html";
		PostMethod postMethod = new PostMethod(url);
		// 填入各个表单域的值
		org.apache.commons.httpclient.NameValuePair[] data = { new org.apache.commons.httpclient.NameValuePair(
				"userStatus", "1"), };
		// 将表单的值放入postMethod中
		postMethod.setRequestBody(data);
		// 执行postMethod
		int statusCode = 0;
		try {
			statusCode = httpClient.executeMethod(postMethod);
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发
		// 301或者302
		if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY
				|| statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
			// 从头中取出转向的地址
			Header locationHeader = postMethod.getResponseHeader("location");
			String location = null;
			if (locationHeader != null) {
				location = locationHeader.getValue();
				System.out.println("diandianLogin:" + location);
			} else {
				System.err.println("Location field value is null.");
			}
			return;
		} else {
			System.out.println(postMethod.getStatusLine());
			String str = "";
			try {
				str = postMethod.getResponseBodyAsString();
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println(str);
		}
		postMethod.releaseConnection();
		return;
	}

		@SuppressWarnings("finally")
	public static String sendSSLPostRequest(String reqURL,
			Map<String, String> params) {
		long responseLength = 0; // 响应长度
		String responseContent = null; // 响应内容
		HttpClient httpClient = new DefaultHttpClient(); // 创建默认的httpClient实例
		X509TrustManager xtm = new X509TrustManager() { // 创建TrustManager
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}

			public void checkClientTrusted(
					java.security.cert.X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
				// TODO Auto-generated method stub

			}

			public void checkServerTrusted(
					java.security.cert.X509Certificate[] arg0, String arg1)
					throws java.security.cert.CertificateException {
				// TODO Auto-generated method stub

			}
		};
		try {
			// TLS1.0与SSL3.0基本上没有太大的差别,可粗略理解为TLS是SSL的继承者,但它们使用的是相同的SSLContext
			SSLContext ctx = SSLContext.getInstance("TLS");

			// 使用TrustManager来初始化该上下文,TrustManager只是被SSL的Socket所使用
			ctx.init(null, new TrustManager[] { xtm }, null);

			// 创建SSLSocketFactory
			SSLSocketFactory socketFactory = new SSLSocketFactory(ctx);

			// 通过SchemeRegistry将SSLSocketFactory注册到我们的HttpClient上
			httpClient.getConnectionManager().getSchemeRegistry()
					.register(new Scheme("https", 443, socketFactory));

			HttpPost httpPost = new HttpPost(reqURL); // 创建HttpPost
			List<NameValuePair> formParams = new ArrayList<NameValuePair>(); // 构建POST请求的表单参数
			for (Map.Entry<String, String> entry : params.entrySet()) {
				formParams.add(new BasicNameValuePair(entry.getKey(), entry
						.getValue()));
			}
			httpPost.setEntity(new UrlEncodedFormEntity(formParams, "UTF-8"));

			HttpResponse response = httpClient.execute(httpPost); // 执行POST请求
			HttpEntity entity = response.getEntity(); // 获取响应实体

			if (null != entity) {
				responseLength = entity.getContentLength();
				responseContent = EntityUtils.toString(entity, "UTF-8");
				EntityUtils.consume(entity); // Consume response content
			}
			System.out.println("请求地址: " + httpPost.getURI());
			System.out.println("响应状态: " + response.getStatusLine());
			System.out.println("响应长度: " + responseLength);
			System.out.println("响应内容: " + responseContent);
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			httpClient.getConnectionManager().shutdown(); // 关闭连接,释放资源
			return responseContent;
		}
	}
}

注释掉的login方法是http请求的。那个sendssl的是用了https的。那个logout也是http请求就可以的虽然 网址是https。再次修改的时候也都改成https请求吧,这样请求的方法写一个就好,引用包也不会这么乱了。这里主要是给大家一个参考 。二是刚写完,有时间再改。


一天之后。

今天试图将java程序移植到android上。以为可以。但是中间遇到了很多问题。而且就算能够把错误都消除了,当new sslsocketfactory的时候还是会卡在这。首先android里边有一个和commen.httpclient一样的包。包名和路径都一样。所以如果出现问题的话需要改一下order and expert里边的包。画上勾。然后将你导入的把移到top。这样可以最先去引用你所导入的包,就酱。然后下面附上android的httpspost

package com.daxiong.wifilogin;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.AllowAllHostnameVerifier;

public class HttpClient {
	private static final AllowAllHostnameVerifier HOSTNAME_VERIFIER = new AllowAllHostnameVerifier();
	private static X509TrustManager xtm = new X509TrustManager() {
		public void checkClientTrusted(X509Certificate[] chain, String authType) {
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	};
	private static X509TrustManager[] xtmArray = new X509TrustManager[] { xtm };
	private static HttpsURLConnection conn = null;

	public static InputStream sendPOSTRequestForInputStream(String path,
			Map<String, String> params, String encoding) throws Exception {
		// 1> 组拼实体数据
		// method=save&name=liming&timelength=100
		StringBuilder entityBuilder = new StringBuilder("");
		if (params != null && !params.isEmpty()) {
			for (Map.Entry<String, String> entry : params.entrySet()) {
				entityBuilder.append(entry.getKey()).append('=');
				entityBuilder.append(URLEncoder.encode(entry.getValue(),
						encoding));
				entityBuilder.append('&');
			}
			entityBuilder.deleteCharAt(entityBuilder.length() - 1);
		}
		byte[] entity = entityBuilder.toString().getBytes();
		URL url = new URL(path);
		conn = (HttpsURLConnection) url.openConnection();
		if (conn instanceof HttpsURLConnection) {
			// Trust all certificates
			SSLContext context = SSLContext.getInstance("TLS");
			context.init(new KeyManager[0], xtmArray, new SecureRandom());
			SSLSocketFactory socketFactory = context.getSocketFactory();
			((HttpsURLConnection) conn).setSSLSocketFactory(socketFactory);
			((HttpsURLConnection) conn).setHostnameVerifier(HOSTNAME_VERIFIER);
		}
		conn.setConnectTimeout(5 * 1000);
		conn.setRequestMethod("POST");
		conn.setDoOutput(true);// 允许输出数据
		conn.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded");
		conn.setRequestProperty("Content-Length", String.valueOf(entity.length));
		OutputStream outStream = conn.getOutputStream();
		outStream.write(entity);
		outStream.flush();
		outStream.close();
		if (conn.getResponseCode() == 200) {
			return conn.getInputStream();
		}
		return conn.getInputStream();
	}

	public static void closeConnection() {
		if (conn != null)
			conn.disconnect();
	}
}

另外这个返回值是一个输入流需要用下面的这个方法转化一下。

	public String inputStream2String(InputStream in) throws IOException {
		StringBuffer out = new StringBuffer();
		byte[] b = new byte[4096];
		for (int n; (n = in.read(b)) != -1;) {
			out.append(new String(b, 0, n));
		}
		return out.toString();
	


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android中的Wi-Fi代码实现了Wi-Fi连接、扫描、配置Wi-Fi网络等功能。通过分析Wi-Fi代码,可以了解到Android中如何管理和操作Wi-Fi网络。 首先,Wi-Fi代码的核心是WifiManager类,它提供了许多方法来操作Wi-Fi功能。通过WifiManager,我们可以获取当前连接的Wi-Fi网络的信息,可以获取已经配置的Wi-Fi网络列表,也可以配置和连接Wi-Fi网络。同时,WifiManager还提供了用于开启和关闭Wi-Fi功能的方法。 其次,Android通过BroadcastReceiver来监听Wi-Fi的状态变化,例如Wi-Fi网络连接成功与否的事件。这样,我们可以通过注册该BroadcastReceiver来实时获取Wi-Fi状态的变化。 另外,Android还提供了WifiInfo类,用于获取关于Wi-Fi网络连接的详细信息,包括当前连接的Wi-Fi网络名称、信号强度、速度等。 在Wi-Fi扫描方面,Android提供了WifiManager.startScan()方法来启动Wi-Fi扫描。扫描结果可通过注册ScanResultReceiver来获取,该Receiver将接收到扫描结果并存储在ScanResult对象中。ScanResult包含了扫描到的Wi-Fi网络的信息,如网络名称、信号强度等。 最后,Android还提供了WifiConfiguration类,用于配置Wi-Fi网络。通过该类,我们可以设置网络的SSID(网络名称)、密码、加密方式等信息,然后调用WifiManager.addNetwork()方法将配置好的网络添加到已有的Wi-Fi网络列表中。 总之,通过对Android的Wi-Fi代码进行分析,我们可以了解到Android中Wi-Fi的管理和操作逻辑,从而能够更好地理解和应用Wi-Fi功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值