主體步驟
1. 筆記本裝fiddler;獵豹WiFi開熱點;
2. 手機連接熱點,WiFi設置代理-手動-主機為192.168.1.1,端口為8888;
3. 手機瀏覽器訪問fiddler代理ip+端口,如獵豹WiFi是192.168.191.1:8888,安裝fiddler證書到手機;否則app是不給聯網的。
4. 抓app的包。
5. 分析app登錄、簽到時都干了什么。
更多關於fiddller參考:
http://chessman-126-com.iteye.com/blog/2001501
http://www.cnphp6.com/archives/97865
http://www.cnblogs.com/mfryf/p/5028010.html
具體實施
好,假設你已經做好了准備工作。
(1)第一步,device_open
當有道雲筆記app打開時,app訪問device_open,fiddler抓到的包:
注意返回的delusers數組,刪除用戶?怪嚇人的。
上圖是POST請求,下圖是服務器返回(下同)。


(2)第二步,login
如圖,重點是請求時發送的usertoken,這個是app內部產生的。
這個token變化的頻率是?
經測試,退出app后再次打開,此token沒有變化。或許是每天變化一次。后面測試。
服務器返回的就是set-cookie了。usertoken不變,cookie就不用變。


(3)login后的很多請求使用cookie
在這之后app的自動請求已有LOGIN=true的cookie了。

(4)點擊簽到訪問服務器 checkin 方法
點擊簽到按鈕,請求checkin method

返回簽到是否成功,簽到得到的空間等等。

2016/05/10 09:50
今天打開筆記簽到,user token 沒變,cookie也沒變。
2016/05/11 13:44
user token 和 cookie 依舊沒變。
由此推論,只要
app運行的環境不改變,發送給server的token不會變,返回的cookie不會變。
退出賬號后再次登錄,user token會改變。僅退出app(登錄狀態是保留的),下次打開app自動登錄,user token 不改變。
好,下面上代碼。關鍵是main函數中的三個方法,模擬了你打開app-點擊簽到按鈕的這個過程。
程序中有的參數需要自己抓包然后放進去。

1 import java.io.BufferedReader; 2 import java.io.IOException; 3 import java.io.InputStreamReader; 4 import java.io.OutputStream; 5 import java.net.HttpURLConnection; 6 import java.net.MalformedURLException; 7 import java.net.URL; 8 9 10 import java.io.PrintWriter; 11 import java.net.URLConnection; 12 import java.util.*; 13 import java.io.*; 14 import java.util.zip.GZIPInputStream; 15 import java.io.UnsupportedEncodingException; 16 17 public class Signin { 18 public static String seesion_cookie = null; 19 20 public static void main(String[] args) throws IOException { 21 /* 22 * set proxy so that fiddler 23 * can capture packages sent by this program 24 System.setProperty("http.proxyHost", "127.0.0.1"); 25 System.setProperty("https.proxyHost", "127.0.0.1"); 26 System.setProperty("http.proxyPort", "8888"); 27 System.setProperty("https.proxyPort", "8888"); 28 System.setProperty("javax.net.ssl.trustStore", 29 "D:\\Program Files\\Java\\jre1.8.0_25\\lib\\security\\FiddleKeystore"); 30 System.setProperty("javax.net.ssl.trustStorePassword", "your_passwd"); 31 */ 32 33 System.out.println("deviceOpen:" + deviceOpen()); 34 System.out.println("login:" + login()); 35 System.out.println("checkIn:" + checkIn()); 36 37 } 38 39 public static String deviceOpen() { 40 String url = "http://note.youdao.com/yws/device_open/poll"; 41 String arg = "your_arg"; 42 Map<String, String> headers = new HashMap<String, String>(); 43 headers.put("Content-Length", "481"); 44 headers.put("Content-Type", "application/x-www-form-urlencoded"); 45 46 return sendPost(url, arg, headers); 47 } 48 49 public static String login() { 50 String url = "http://note.youdao.com/login/acc/co/cq?product=YNOTE&cf=7&userid=......."; 51 String arg = null; 52 Map<String, String> headers = new HashMap<String, String>(); 53 headers.put("Content-Length", "0"); 54 headers.put("YNOTE-PC", "v2|urstoken||YNOTE|......"); 55 56 return sendPost(url, arg, headers); 57 } 58 59 public static String checkIn() { 60 String url = "https://note.youdao.com/yws/mapi/user?method=checkin"; 61 String arg = "your_arg"; 62 Map<String, String> headers = new HashMap<String, String>(); 63 headers.put("Cookie", "YNOTE_LOGIN=true;" + seesion_cookie); 64 headers.put("Content-Length", "481"); 65 headers.put("Content-Type", "application/x-www-form-urlencoded"); 66 67 return sendPost(url, arg, headers); 68 } 69 70 71 72 public static String sendPost(String url, String param, Map<String, String> headers) { 73 PrintWriter out = null; 74 BufferedReader in = null; 75 StringBuilder result = new StringBuilder(); 76 try { 77 URL realUrl = new URL(url); 78 79 HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); 80 conn.setRequestMethod("POST"); 81 82 conn.setRequestProperty("Accept-Encoding", "gzip"); 83 conn.setRequestProperty("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3"); 84 for (String key : headers.keySet()) 85 conn.setRequestProperty(key, headers.get(key)); 86 conn.setRequestProperty("Host", "note.youdao.com"); 87 conn.setRequestProperty("Connection", "Keep-Alive"); 88 conn.setRequestProperty("User-Agent", "ynote-android"); 89 90 conn.setDoOutput(true); 91 conn.setDoInput(true); 92 93 out = new PrintWriter(conn.getOutputStream()); 94 if (param != null) out.print(param); 95 out.flush(); 96 System.out.println(conn.getResponseCode() + " " + conn.getResponseMessage()); 97 98 for (int i = 1; conn.getHeaderFieldKey(i) != null; ++i) { 99 if (conn.getHeaderFieldKey(i).equals("Set-Cookie") && 100 conn.getHeaderField(i).contains("YNOTE_SESS=v2")) { 101 seesion_cookie = conn.getHeaderField(i).split(";")[0]; 102 System.out.println("seesion_cookie:" + seesion_cookie); 103 break; 104 } 105 } 106 107 Reader reader = null; 108 if ("gzip".equals(conn.getContentEncoding())) { 109 System.out.println("Response body is encoded in gzip."); 110 reader = new InputStreamReader(new GZIPInputStream(conn.getInputStream())); 111 } else { 112 reader = new InputStreamReader(conn.getInputStream()); 113 } 114 115 in = new BufferedReader(reader); 116 String line; 117 while ((line = in.readLine()) != null) { 118 result.append(line); 119 } 120 } catch (Exception e) { 121 System.out.println("sendPost Exception !!! " + e); 122 e.printStackTrace(); 123 } 124 125 finally { 126 try { 127 if (out != null) out.close(); 128 if (in != null) in.close(); 129 } catch (IOException ex) { 130 ex.printStackTrace(); 131 } 132 } 133 134 return result.toString(); 135 } 136 }

2016/05/12 00:53
把程序放在服務器上:

設置crontab例行任務

# signin.sh cd /home/whuliss/Documents/ date >> signin_log java SignIn >> signin_log
log:
Fri Jun 3 00:37:01 CST 2016 checkIn:{"total":830472192,"time":1464885510110,"space":6291456,"success":1} Sat Jun 4 00:37:01 CST 2016 checkIn:{"total":834666496,"time":1464971913651,"space":4194304,"success":1} Sun Jun 5 00:37:02 CST 2016 checkIn:{"total":840957952,"time":1465058318146,"space":6291456,"success":1} Mon Jun 6 00:37:01 CST 2016 checkIn:{"total":842006528,"time":1465144721286,"space":1048576,"success":1} Tue Jun 7 00:37:01 CST 2016 checkIn:{"total":847249408,"time":1465231125472,"space":5242880,"success":1} Wed Jun 8 00:37:01 CST 2016 checkIn:{"total":852492288,"time":1465317528907,"space":5242880,"success":1}