目录
前言
最近项目要求访问其他设备页面获取数据,页面多数使用https请求,用过一段时间,用过两种不同的方式,看过其他大佬们的帖子,自己总结后,在此记录一下。http请求变为https请求最主要的就是重写自己的协议认证方式。
正文
本文分为 HttpPost 和 HttpsURLConnection 两种方法,HttpsURLConnection是jdk自带jar包,HttpPost 是外部引入。
HttpPost发送https请求方式
1.引入依赖包
首先引入项目依赖的包,HttpsURLConnection是jdk自带的不需要引入,下面是引入HttpPost 依赖包。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.8</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.11</version>
<scope>test</scope>
</dependency>
2.重写HttpClient
public class SSLClient extends DefaultHttpClient {
public SSLClient() throws Exception{
super();
//Https分为TLS和SSL两种协议,TLS可以当做SSL3.1版本(不兼容增强版)
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = this.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));
}
}
3.发送请求默认带参,不传参为null就行
public static HttpResponse post(String url, Map<String, String> parammap) {
HttpClient httpClient = null;
HttpPost httpPost = null;
HttpResponse response = null;
try {
// 创建默认客户端
httpClient = new SSLClient();
// 创建Post请求实例
httpPost = new HttpPost(url);
// 创建参数列表
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> entry : parammap.entrySet()) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
// 将参数进行封装,提交到服务器端
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF8"));
//根据自己需求,可以换成其他方式
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpPost.setHeader("Accept-Encoding", "gzip, deflate");
httpPost.setHeader("Connection", "keep-alive");
httpPost.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
response = httpClient.execute(httpPost);
//根据需求获取自己需要的cookie,我项目中需要两个
String CookieStr = StringHandleUtil.getCookie(response);
String XcsrfidStr = StringHandleUtil.getXCSRF(response);
HttpEntity entity = response.getEntity();
try {
InputStream content = entity.getContent();
entity_content = RequestUtil.ConvertStreamToString(content);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
// 释放资源
httpPost.abort();
}
return response;
}
4.附上cookie获取代码
public static String getCookie(HttpResponse httpResponse){
//获取响应头信息
Header[] headers = httpResponse.getAllHeaders();
List<String> list = new ArrayList<String>();
for (Header header : headers) {
System.out.println(header.getName() + ": " + header.getValue());
//可能不同项目有大小写区别,酌情修改
if(!header.getName().equals("Set-Cookie")){
list.add(header.getValue());
}
}
//我项目中有多个cookie,所以获取多个
String setCookieA = list.get(0);
String setCookieB = list.get(1);
if(setCookieA.length()>setCookieB.length()){
return setCookieA;
}else{
return setCookieB;
}
}
HttpsURLConnection发送https请求方式
1.重写X509TrustManager
HttpsURLConnection不需引入其他依赖,直接使用jdk自带包即可(jdk1.7以上就可以,我使用的是jdk1.8)
public class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
2.发送https请求
public static String testget(String url,String cookie) throws Exception {
// 拼凑get请求的URL字串,使用URLEncoder.encode对特殊和不可见字符进行编码
SSLContext sslcontext = null;
DataOutputStream out = null;
sslcontext = SSLContext.getInstance("TLS");
TrustManager[] tm = {new MyX509TrustManager()};
sslcontext.init(null, tm, new SecureRandom());
HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
};
URL postUrl = new URL(url);
// 根据拼凑的URL,打开连接,URL.openConnection函数会根据URL的类型,
// 返回不同的URLConnection子类的对象,这里URL是一个http,因此实际返回的是HttpURLConnection
HttpsURLConnection connection = (HttpsURLConnection) postUrl.openConnection();
connection.setSSLSocketFactory(sslcontext.getSocketFactory());
connection.setHostnameVerifier(ignoreHostnameVerifier);
//不填写默认是get请求
connection.setRequestMethod("POST");
//post请求必须设置output,需要传输参数,不设置默认为false
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Connection", "Keep-Alive");
//需要传输cookie则加上,不需要可以删除
if(null != cookie) {
connection.setRequestProperty("Cookie", cookie);
}
// 进行连接,但是实际上get request要在下一句的connection.getInputStream()函数中才会真正发到
connection.connect();
//所有参数可以使用key=value的格式用 & 符号拼接起来,满足通常的post和get请求
//例:https://192.168.11.11/pro?username=admin&password=admin123!
String param = "username=admin&password=admin123!";
out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(param);
out.flush();
// 取得输入流,并使用Reader读取
BufferedReader reader = new BufferedReader(new InputStreamReader(
connection.getInputStream(),"UTF-8"));
System.out.println("Contents of get request:");
String result="";
String lines;
while ((lines = reader.readLine()) != null) {
System.out.println(lines);
result+=lines;
}
System.out.println(connection.getHeaderFields());
//获取连接头中的cookie
String CookieStr = StringHandleUtil.getCookie2(connection.getHeaderFields().get("Set-cookie"));
reader.close();
//请求处理完之后关闭
connection.disconnect();
return result;
}
3.附上cookie获取方法
HttpsURLConnection和httppost请求获取的response不同,所以获取的方式也有些不一样,下面附上代码
public static String getCookie2(List<String> list){
//获取响应头信息
String setCookieA = replaceCookie(list.get(0));
String setCookieB = replaceCookie(list.get(1));
for (String string : list) {
//特定cookie请求头,可以根据项目修改或者删除
if(string.indexOf("AIROS_1EA05E57CC5F") != -1)
return replaceCookie(string);
}
return setCookieA+"; "+setCookieB;
}