最近在擼一個V2EX的客戶端,官方API缺少一些功能如登錄哟沫,發(fā)帖等询吴,擼完官方API總覺得少了什么,本篇文章主要通過模擬登錄實現(xiàn)一些官方?jīng)]提供API的功能
觀察登錄傳輸?shù)臄?shù)據(jù)
在網(wǎng)頁上登錄帳號栈虚,通過chrome的調(diào)試模式可以看到 ,我們傳了4個數(shù)據(jù)給服務器史隆,分別是帳號魂务,密碼,once泌射,和next粘姜,once是用來驗證是否人為操作的標志,POST時必須帶上這個字段熔酷,否則會認為是非人為操作而被禁止訪問孤紧。
知道了需要傳什么參數(shù)后,退出登陸拒秘,回到登錄之前的頁面号显,https://www.v2ex.com/signin, 我們需要POST的數(shù)據(jù)都需要在這個頁面里捉取下來
代碼實現(xiàn)
1.添加請求頭
在chrome登陸成功頁面查看POST的請求頭躺酒,在OkHttp中相應進行配置押蚤。
mClient = new OkHttpClient.Builder()
.cookieJar(new CustomCookieJar(new CookieManager(mPersistentCookieStore, CookiePolicy.ACCEPT_ALL)))
.readTimeout(12, TimeUnit.SECONDS)
.addInterceptor(htmlInterceptor)
.addInterceptor(loggingInterceptor)
.build();
private Interceptor htmlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Origin", "https://www.v2ex.com")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
return chain.proceed(newRequest);
}
};
2.定義登錄接口api
分別定義get和Post 兩種,get取得帳號羹应,密碼揽碘,once的值,用于POST提交
@GET("signin") //登錄
Observable<String> login();
@FormUrlEncoded
@Headers("Referer: https://www.v2ex.com/signin")
@POST("signin")
Observable<String> postLogin(@FieldMap HashMap<String, String> hashMap);
3獲取數(shù)據(jù)园匹,發(fā)送登陸請求
Subscription subscription = LoginService.getInstance().auth().login()
.map(new Func1<String, HashMap>() {
@Override
public HashMap call(String stringResponse) {
return JsoupUtil.parseUserNameAndPwd(stringResponse, username, password);
}
}).flatMap(new Func1<HashMap, Observable<String>>() {
@Override
public Observable<String> call(HashMap requestMap) {
return LoginService.getInstance().auth().postLogin(requestMap);
}
}).map(new Func1<String, LoginResult>() {
@Override
public LoginResult call(String response) {
String errorMsg = ApiErrorUtil.getErrorMsg(response);
if (errorMsg == null) {
return JsoupUtil.parseLoginResult(response);
} else {
LoginResult result = new LoginResult();
result.setMessage(errorMsg);
return result;
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
這里使用了Jsoup來解析html可以很便捷的獲取需要的數(shù)據(jù)雳刺,沒了解過的同學可以查看這里Jsoup開發(fā)指南
登錄成功后返回的html里面就有用戶的數(shù)據(jù)了
Cookie
當你完成已上步驟還是無法獲取個人信息,會自動跳轉(zhuǎn)到登陸頁面裸违,因為http請求是無狀態(tài)的煞烫,服務器并不知道你已經(jīng)登錄了,這里就需要配置Cookie累颂,登錄成功后滞详,服務會返回一個Cookie(通行證)凛俱,客戶端需保存這個Cookie,再次發(fā)送請求時帶上這個Cookie料饥,服務器就能識別該用戶蒲犬,并且返回用戶相關(guān)的信息了。
在OKHttp3中配置Cookie持久化只需一句話
.cookieJar(new CustomCookieJar(new CookieManager(mPersistentCookieStore, CookiePolicy.ACCEPT_ALL)))
實現(xiàn)Cookie后就可以獲取所有數(shù)據(jù)了岸啡,如用戶關(guān)注節(jié)點等原叮。
對cookie不了解的可以看這里 Cookie/Session機制詳解
在OkHttp中如何實現(xiàn)Cookie的持久化可以看這里OkHttp3之Cookies管理及持久化
以上完整的代碼在這里 https://github.com/sooola/V2EX-Android ,RxJava &Retrofit 的V2EX第三方客戶端巡蘸,項目在龜速更新中奋隶,有任何建議歡迎issues,開源不易悦荒,路過求start鼓勵下(⊙?⊙)