我在我的应用程序中使用 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”页面。
当它给出该错误时,它往往会继续这样做,尽管在几次调用后它确实会再次恢复工作。所以这很不一致。
我尝试过很多事情,例如:
它不会让步,这里有人知道可能导致此问题的原因吗?
以下是相关内容: 我有一个带有静态 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 { }
}
我想我通过添加暂停来修复它,有一段时间没看到它了。
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 毫秒的暂停似乎给了它足够的时间来将页面传送出去。