java 模擬web登陸httpClient並保存cookie


場景:調用接口完成某項操作,但是接口是強登錄的,需要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 HttpClient(); 

 

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失效重新請求的實現方法有點不太好,希望大家多多交流;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM