HttpListener“无法访问此站点”

问题描述 投票:0回答:1

我在我的应用程序中使用 OAuth 并启动外部浏览器让用户登录,然后使用 HttpListener 将 returnUri 捕获到本地主机。

事实是,这个监听器大多数时候都能正确渲染网页,但有时它会在 Chrome 中显示“无法访问此站点”异常。

This site can’t be reachedlocalhost refused to connect.
Try:

Checking the connection
Checking the proxy and the firewall
ERR_CONNECTION_REFUSED

发生这种情况时,它不会引发异常。

我确实从 http.GetContext() 获取上下文,因此侦听器确实捕获本地主机上的浏览器请求,但由于某种原因,浏览器有时会显示错误消息,而不是呈现“login succes.html”页面。

当它给出该错误时,它往往会继续这样做,尽管在几次调用后它确实会再次恢复工作。所以这很不一致。

我尝试过很多事情,例如:

  • 在 UI 线程上运行它(因此没有后台任务)
  • 关闭监听器并创建一个新监听器,现在我有一个 我启动和停止的静态监听器,尽管这似乎不是 很重要。
  • Thread.Sleep(100) 查看是否可能是死锁或 一些东西。

它不会让步,这里有人知道可能导致此问题的原因吗?

以下是相关内容: 我有一个带有静态 HttpListener 的模态形式:

static HttpListener http = new HttpListener();

然后,表单在后台线程上启动登录代码(以保持 UI 响应):

Task.Run(SignInOIDC);

        private void SignInOIDC() {
     try {

         if (!http.Prefixes.Contains(OidcOptions.RedirectUri)) http.Prefixes.Add(OidcOptions.RedirectUri);
         http.Start();

         // todo use the logout url https://stackoverflow.com/questions/52302863/logging-out-from-identityserver-quietly
         _client = new OidcClient(OidcOptions);
         _loginState = _client.PrepareLoginAsync().Result;

        

         // open system browser to start authentication
         var uri = _loginState.StartUrl;
         var proc = Process.Start(_loginState.StartUrl);

         // wait for the authorization response.
         var context = http.GetContext(); // blocking call, it does return from this so it catches the request         
         WriteLoginSucceeded(context);               
         var formData = context.Request.Url.ToString();
         ShutdownHttp();
         this.Activate();   
          
         // read token
         OIDCLoginResult = _client.ProcessResponseAsync(formData, _loginState).Result;
       
         if (_cancelled) return;
         this.Invoke((MethodInvoker)delegate {
             DialogResult = DialogResult.OK; // this closes the form
         });
     }
     catch (Exception ex) {               
         var msg = Util.ReadException(ex);
         MessageBox.Show(msg);               
     }
     finally {
         ShutdownHttp();
     }
 }


        private string _hmtl;
        private string HTML { get {
                if (_hmtl == null) {
                    var fld = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                    var path = Path.Combine(fld, "LoginSuccess.html");
                    _hmtl = File.ReadAllText(path);
                }
                return _hmtl;
            } }

        private void WriteLoginSucceeded(HttpListenerContext context) {            
            HttpListenerResponse response = context.Response;
            byte[] buffer = Encoding.UTF8.GetBytes(HTML);
            response.ContentLength64 = buffer.Length;
            Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            output.Close();
        }
 private void ShutdownHttp() {
     try {
         if (http != null) {
             if (http.IsListening) http.Stop();                  
         }
     }
     catch { }
 }
c# winforms httplistener
1个回答
0
投票

我想我通过添加暂停来修复它,有一段时间没看到它了。

  private void WriteLoginSucceeded(HttpListenerContext context) {            
      HttpListenerResponse response = context.Response;
      byte[] buffer = Encoding.UTF8.GetBytes(HTML);
      response.ContentLength64 = buffer.Length;
      Stream output = response.OutputStream;
      output.Write(buffer, 0, buffer.Length);
      output.Flush();
      output.Close();
      Thread.Sleep(150);
  }

看起来表单会很快关闭,调用 ShutDownHttp 方法。这 150 毫秒的暂停似乎给了它足够的时间来将页面传送出去。

© www.soinside.com 2019 - 2024. All rights reserved.