场景:调用接口完成某项操作,但是接口是强登录的,需要cookie, 且cookie会过期;服务器会限制登录的次数,如果一个账号频繁登录,则在短时间内无法正常登录,因此无法做到每调用接口一次就登录一次,且这样的效率也会比较低;
方法: 采用httpClient获取cookie, 并在接口上加入cookie校验;
核心代码:
0. 需要加入的jar包
1 import org.apache.commons.lang.StringUtils;
2 import org.apache.commons.httpclient.HttpClient;
3 import org.apache.commons.httpclient.methods.GetMethod;
4 import org.apache.http.Header;
5 import org.apache.http.HttpResponse;
6 import org.apache.http.HttpStatus;
7 import org.apache.http.StatusLine;
8 import org.apache.http.client.CookieStore;
9
10 import org.apache.http.client.HttpClient;
11 import org.apache.http.client.methods.HttpGet;
12 import org.apache.commons.httpclient.methods.GetMethod;
13
14 import org.apache.http.client.methods.HttpPost;
15
16 import org.apache.http.cookie.Cookie;
17 import org.apache.http.impl.client.BasicCookieStore;
18
19 import org.apache.http.impl.client.HttpClients;
20 import org.apache.http.protocol.BasicHttpContext;
21 import org.apache.http.protocol.HttpContext;
View Code
需要导入pom.xml文件的依赖
1 <dependency>
2 <groupId>org.apache.httpcomponents</groupId>
3 <artifactId>httpclient</artifactId>
4 <version>4.5.5</version>
5 </dependency>
6 <dependency>
7 <groupId>commons-httpclient</groupId>
8 <artifactId>commons-httpclient</artifactId>
9 <version>3.1</version>
10 </dependency>
1. 获取cookie, 其中
getUrl(loginUrl, username, password); 是将url进行拼接,loginUrl 加上登陆需要的参数拼接为一个请求, 其中loginUrl就是登录url
public String getCookies(String username, String password){
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(COOKIE_STORE, cookieStore);
HttpClient client = HttpClients.createDefault();
String authUrl = getUrl(loginUrl, username, password);
System.out.println("authUrl = " + authUrl);
HttpPost post = new HttpPost(authUrl);
try {
response = client.execute(post, localContext);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
System.out.println("first execute code :" + statusCode);
if(statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY){
Header firsRedirectHeader = response.getFirstHeader("location");
String firstRedirectUrl = firsRedirectHeader.getValue();
HttpGet get = new HttpGet(firstRedirectUrl);
HttpResponse getResponse = client.execute(get, localContext);
StatusLine statusLine2 = getResponse.getStatusLine();
int statusCode2 = statusLine2.getStatusCode();
System.out.println("second execute code :" + statusCode2);
System.out.println("cookie :" + cookieStore.getCookies());
List<Cookie> cookieList = cookieStore.getCookies();
StringBuffer tmpCookie = new StringBuffer();
for(int i = 0 ; i < cookieList.size(); i++) {
tmpCookie.append(cookieList.get(i).getName()).append("=");
tmpCookie.append(cookieList.get(i).getValue()).append(";");
tmpCookie.append("domain=").append(cookieList.get(i).getDomain()).append(";");
tmpCookie.append("path=").append(cookieList.get(i).getPath()).append(";");
}
get.releaseConnection();
return tmpCookie.toString();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(post != null){
post.releaseConnection();
}
}
return "-1";
}
View Code
// formData 里面需要填充的内容根据浏览器f12调试模式中,获取到请求的信息
private String getUrl(String url, String username, String password){
if(StringUtils.isEmpty(url)){
System.out.println("url is empty");
return "-1";
}
formData = new HashMap<String, String>();
formData.put("username", username);
formData.put("password", password);
formData.put("app", "web");
formData.put("product", "xxx");//产品根据实际情况定
formData.put("tp", "urstoken");
formData.put("cf", "7");
formData.put("fr", "1");
formData.put("ru", "https://xxxxxxxn"); //链接可以根据自己在浏览器的信息中拿到,不同的登录该部分地址是不一样的
formData.put("er", "https://xxxxx");
String arguments = MaptoUrl(formData);
return url + arguments;
}
public String MaptoUrl(Map<String, String> map){
String arguments="?";
Iterator iterator = map.entrySet().iterator();
Boolean first_args = true;
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry) iterator.next();
Object key = entry.getKey();
Object val = entry.getValue();
String key_str = (String) key;
String val_str = (String) val;
if(first_args == false){
arguments = arguments + "&";
}
first_args = false;
arguments = arguments + key_str;
arguments = arguments + "=";
arguments = arguments + val_str;
}
return arguments;
}
2. 获取到有效的cookie, 因为第一步获取到cookie后,cookie在一段时间内可能会失效,因此为了后面接口中带入有效的cookie, 这里还需要该函数来获取真正有效的cookie;
public String getValidCookie(String cookie){
if(cookie.contains("DICT_SESS")){
return cookie;
}else{
Login login = new Login();
String validCookie = login.getCookies(username, password);
return validCookie;
}
}
3. 真正执行接口的代码, for循环2次,第一次是去请求接口,如果接口返回的结果是403权限被拒绝,则需要调用login.getValidCookie()方法登录一次,获取真正的cookie.,然后进行第二次接口请求;
如果接口返回的结果是0, 则表示cookie依然有效,则直接返回true; 其中参数url是需要真正请求的接口;
1 public Boolean executeMethod(String url) {
2 String result = "-1";
3 for(int i = 0; i < 2; i++) {
4 GetMethod getMethod = new GetMethod(url);
5 getMethod.setRequestHeader("cookie", cookie);
6 try {
7 httpClient.executeMethod(getMethod);
8 System.out.println("method result = " + getMethod.getResponseBodyAsString());
9 result = getMethod.getResponseBodyAsString();
10 } catch (IOException e) {
11 e.printStackTrace();
12 }
13 JSONObject obj = JSONObject.parseObject(result);
14 if ("0".equals(obj.get("err").toString())) {
15 return true;
16 }else if ("403".equals(obj.get("err").toString())) {
17 cookie = login.getValidCookie(cookie);
18 continue;
19 }else{
20 return false;
21 }
22 }
23 return false;
24
25 }
4. 在类加载的时候先登录一次,保存cookie,且是全局变量;则在第3步更新cookie的时候,就可以更新该变量;
1 Login login = new Login();
2 private String cookie = login.getCookies(username, password);
3 HttpClient httpClient = new
public static void main(String[] args) {
Login httpclientDemo = new Login();
org.apache.commons.httpclient.HttpClient httpClient = new org.apache.commons.httpclient.HttpClient();
String cookie = httpclientDemo.getCookies("username", "password");
System.out.println("final cookie = " + cookie);
String url = yyyyy";//需要请求的url
GetMethod getMethod = new GetMethod(url);
getMethod.setRequestHeader("cookie", cookie);
try {
httpClient.executeMethod(getMethod);
System.out.println("method result = " + getMethod.getResponseBodyAsString());
} catch (IOException e) {
e.printStackTrace();
}
}
总结: 第三步判断cookie失效重新请求的实现方法有点不太好,希望大家多多交流;