延續餘票查詢,本文實現 12306 自動登錄功能。核心難點在於 HTTPS 證書驗證繞過、動態驗證碼獲取、登錄表單參數構造。採用 WPF 構建測試介面,核心邏輯封裝於 Login12306Manager 靜態類。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, errors) => true;
或封裝為 Messenger 事件總線模式(代碼中略)。
GET https://dynamic.12306.cn/otsweb/passCodeNewAction.do?module=login&rand=sjrand&{random},保存 Cookie。loginRand:POST https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest,解析 JSON 返回 loginRand。POST https://dynamic.12306.cn/otsweb/loginAction.do?method=login,關鍵參數:loginRand={0}&refundLogin=N&refundFlag=Y&isClick=&form_tk=null
&loginUser.user_name={1}&nameErrorFocus=
&user.password={2}&passwordErrorFocus=
&randCode={3}&randErrorFocus=
&NDU0NzY4NA%3D%3D=Nzg4ZDAxMGNkYTZlMTRjZA%3D%3D
&myversion=undefined
三個動態值:loginRand、用戶名、密碼、驗證碼。
isLogin=true + u_name → 登錄成功private void ButtonLogin_Click(object sender, RoutedEventArgs e) {
string html = Login12306Manager.Login(txtUserName.Text, txtPassword.Password, txtRandCode.Text);
rtxResultContent.AppendText(html);
}
private void ButtonRefreshRandCode_Click(object sender, RoutedEventArgs e) {
string path = Login12306Manager.RefreshCode(); // 返回本地圖片路徑
if (File.Exists(path)) imageRandCode.Source = new BitmapImage(new Uri(path));
}
Login12306Manager.Login(user, pwd, randCode) → 返回登錄結果字符串Login12306Manager.RefreshCode() → 下載驗證碼圖片,返回本地路徑Login12306Manager.DoGetLoginRand() → 獲取 loginRandMessenger 事件總線用於日誌輸出BeforLoginRnad DTO 對應 JSON 反序列化項目源碼:Test12306AutoLogin (.NET 4.0, VS2010)