先讲原理:
通俗的讲,登录一个需要basic authentication 的url,首次需要账号和密码,然后才能进入,不是首次的一段时间内,不需要密码也可以进入了。
那么用Http 机制来讲的话就是,首先发送一个带有账号和密码的resquest,并且这个账号密码需要base64加密,发送给登录页,返回一个response和cookie,然后用这个cookie直接去做登录。还有其他方法,但是我用这种方法。
注意几个地方:
1是用post还是用get方法发请求。
2不同jar包不要混用
3和看到的登录情况不一样,我这个是先找登录页面去做一次登录,返回来的去其他的url取数据,区分登录页面和真实内容的url,不是同一个url。
4jar包都是org.apche.http开头的
org.apache.httpcomponents
httpclient
4.5.1
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
public class XOIAccess {
private String loginUrl;
private String userName;
private String password;
private String authCookie;
private Date authCookieExpired = null;
public XOIAccess(String loginUrl, String username, String password) {
this.loginUrl = loginUrl;
this.userName = username;
this.password = password;
}
public void doLogin() throws Exception {
if (!isExpired())
return;
//首先加密 还有基于另外jar包的加密,是一个basic64加密
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(this.userName, this.password));
//把加密账号密码加载到httClient里
CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider)
.build();
//给登录页发送请求 这里头有账号密码的
HttpGet httpGet = new HttpGet(this.loginUrl);
HttpResponse response = httpClient.execute(httpGet);
//这时候response就是有要拿到的内容,可对response各种操作,这里用的是org.apache.http.HttpResponse;
//那么其实这一步我是拿http头cookie,这个头的name就是"Set-Cookie",还有其他头,命名都是固定的。
Header cookieHeader = response.getFirstHeader("Set-Cookie");
if (cookieHeader != null) {
this.authCookie = cookieHeader.getValue();
//这些是对cookie的时间进行一个操作,保存时间,下次进页面的时候用来判断
int start = this.authCookie.indexOf("expires=");
if (start >= 0) {
String expires = this.authCookie.substring(start);
start = expires.indexOf("=");
int end = expires.indexOf(";");
if (start >= 0 && end > 0 && end > start + 1) {
expires = expires.substring(start + 1, end).trim();
DateFormat df = new SimpleDateFormat("E, dd-MMM-yyyy HH:mm:ss z");
this.authCookieExpired = df.parse(expires);
}
}
if (this.authCookieExpired == null) {
throw new Exception("invalid auth cookie:" + this.authCookie);
}
} else {
throw new Exception("Login exception. LoginUrl:" + this.loginUrl + ",username:" + this.userName);
}
}
public String getXmlData(String url) throws Exception {
doLogin();
//CloseableHttpClient Httpclient 是一样的,有点区别
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
//这次把cookie加入头发送出去
//setHeader 和 addHeader 有区别,因为不用名下的Header是一个数组,set是重置,add是往后头添加
HttpGet httpget = new HttpGet(url);
httpget.setHeader("Cookie", this.authCookie);
try {
HttpResponse response = httpclient.execute(httpget);
//这里获取下编码格式
String encoding = "utf-8";
Header encodingHeader = response.getFirstHeader("Content-Encoding");
if(encodingHeader!=null){
encoding = encodingHeader.getValue();
}
//把刚才的格式取出来,转化成一个string
String xml = EntityUtils.toString(response.getEntity(),encoding);
Header errorCodeHeader = response.getFirstHeader("X-XOI-ErrorCode");
if(errorCodeHeader!=null){
String errorCode = errorCodeHeader.getValue();
if(errorCode.trim()!="40401"){
throw new Exception("Fail to get data. url:" + url +",error: \n" + xml);
}else{
return "";
}
}
return xml;
} finally {
httpget.releaseConnection();
}
}
private Boolean isExpired() throws Exception {
//这里是判断当前时间是否过期
if (this.authCookieExpired == null)
return true;
Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("GTM"));
utcCalendar.set(Calendar.MINUTE, 5);
Date utcNow = utcCalendar.getTime();
if (this.authCookieExpired.after(utcNow))
return false;
return true;
}
public static void main(String[] args) throws Exception {
String urlLogin ="";
String urlContent = "";
String username = "";
String password = "";
XOIAccess xoiAccess = new XOIAccess(urlLogin,username, password); //构造
String data = xoiAccess.getXmlData(urlContent); //调用getdata方法 里头会有调用dologin方法
System.out.println("data:\n" + data);
}
}