/// <summary>
        /// 尝试恢复会话
        /// </summary>
        public void TryRecoverSession(Action <string> progressAction)
        {
            if (!File.Exists(_sessionFilePath))
            {
                return;
            }

            try
            {
                var buffer = File.ReadAllText(_sessionFilePath);

                var list   = Newtonsoft.Json.JsonConvert.DeserializeObject <ExportedSession[]>(buffer);
                var valid  = new List <ExportedSession>();
                var client = new WebLib.NetClient();
                foreach (var item in list)
                {
                    if (IsLogined(item.UserName))
                    {
                        continue;
                    }
                    if (progressAction != null)
                    {
                        progressAction(item.UserName);
                    }

                    item.ToSession(null, client);
                    if (client.VerifySessionValid() == true)
                    {
                        var sess = new Session(item.UserName, false, this.Any(s => s.UserName == item.UserName));
                        item.ToSession(sess);
                        Session.OnUserLogined(sess);
                        valid.Add(item);
                    }
                    else if (ProgramConfiguration.Instance.KeepLoginStateAfterRestart)
                    {
                        _waitLogin.Add(item);
                    }
                }

                SaveSessionsToFile();
            }
            catch (Exception ex)
            {
                Events.OnWarning(this, new EventInfoArgs()
                {
                    Message = "无法从本地存储中恢复用户会话,可能记录文件已经损坏"
                });
            }
        }
        private void Context_ValidateResponseHeader(object sender, EventArgs e)
        {
            var ctx      = (HttpContext)sender;
            var response = ctx.Response;

            if (string.Compare(response.ResponseUri.Host, "kyfw.12306.cn", StringComparison.OrdinalIgnoreCase) == -1)
            {
                return;
            }

            var redirection = response.Redirection;

            if (redirection != null && Regex.IsMatch(redirection.Current.ToString(), @"(mormhweb/logFiles|otn/login/error)", RegexOptions.IgnoreCase | RegexOptions.Singleline))
            {
                //系统错误
                throw new SystemBusyException();
            }

            //如果返回了OTN信息,则重置OTN避免掉线
            if (IsUnexpectedLogout(ctx))
            {
                if (ApiConfiguration.Instance.EnableLogoutRescure)
                {
                    Task <bool> task;
                    lock (_lockObject)
                    {
                        task = _resetOtnPortTask;
                        if (task == null)
                        {
                            Debug.WriteLine("OTN重定向已检测到。启动检测任务。");

                            _resetOtnPortTask = Task <bool> .Factory.StartNew(() =>
                            {
                                //先校验原始信息, 最多三次, 只要成功一次即可
                                for (int i = 0; i < 3; i++)
                                {
                                    var ret = VerifySessionValid(noOtnPortCheck: true);
                                    if (ret == true)
                                    {
                                        return(false);
                                    }
                                }

                                if (ctx.ContextData?.ContainsKey("not_important") == true)
                                {
                                    if (_currentOtnPort != null)
                                    {
                                        ResetOtnPort();
                                        return(true);
                                    }
                                }
                                else
                                {
                                    var count      = 0;
                                    var errorCount = 0;
                                    ExportedSession otnSession;
                                    while (count++ < 5 && (otnSession = _currentOtnPort) != null)
                                    {
                                        var client = new NetClient();
                                        otnSession.ToSession(null, client);
                                        var ret = client.VerifySessionValid(noOtnPortCheck: true);
                                        if (ret != null)
                                        {
                                            if (ret == true)
                                            {
                                                _currentOtnPort = new ExportedSession(Session, this);
                                                ResetOtnPort();
                                                return(true);
                                            }
                                            else
                                            {
                                                if (errorCount++ >= 3)
                                                {
                                                    break;
                                                }
                                            }
                                            count--;
                                        }
                                        Thread.Sleep(100);
                                    }
                                }

                                return(false);
                            });

                            task = _resetOtnPortTask;
                        }
                    }

                    task.Wait();
                    _resetOtnPortTask = null;
                    if (task.Result)
                    {
                        Debug.WriteLine("已挽救OTNPORT");
                        throw new Exception("掉线重定向已拦截,请重试");
                    }
                }

                throw new ForceLogoutException();
            }
        }