如何修复 SSO 与 cefSharp 离线浏览器连接到由 self-signed PC 托管的 Web 服务器?
How to fix SSO connet with cefSharp offline browser to webserver hosted by self-signed PC?
TL;DR: 我正在寻找救命稻草,任何人都在使用 CefSharp 的情况下获得了 SSO,并且可以指出我做错了什么?我尝试通过 CefSharp 连接到 SSL-SSO 页面,但它不起作用 - 在 Chrome-Browser 中也不起作用。对于 IE,它 可以正常工作 。我将其添加到受信任的站点 (Proxy/Security),我尝试在注册表中将 whitelist-policy URL 用于 chrome,并尝试了不同的 CefSharp 设置 - 没有任何帮助。
我正在尝试(无济于事)通过 CefSharp-Offline
-浏览连接到启用 SSO 的页面。
用普通IE浏览正常:
- 我得到 302 个答案
- 重定向的网站给我一个 401(未授权)
NTLM, Negotiate
- IE 自动发送
NTLM Auth
并接收 NTLM WWW-Authenticate
- 再过一些 302 后,它以 200 结束,并在网站上显示登录状态
使用 Chrome 69.0.3497.100 浏览失败:
我想这可能是因为网络服务器是在 co-workers PC 上设置的并且使用了 self-signed 证书。
F12-在IE/Chrome中调试:
在 IE 中,我看到一个 302,然后是两个 401 答案,最后在登录站点上结束。
在 chrome 中,我只看到 302 和 200 个答案,并在 "fallback" 登录站点上结束 user/pw 条目。
(302 之一)请求 headers 的主要区别是 NEGOTIATE
与 NTLM
// IE:
Authorization: NTLM TlRMT***==
// Chrome:
Authorization: Negotiate TlRMT***==
Upgrade-Insecure-Requests: 1
DNT: 1
到目前为止,我无法通过 CefSharp 进行连接,我只是登陆了它 RequestHandler.GetAuthCredentials()
- 我不想通过它传递任何凭据。
我试图让它在内部工作的内容 Windows / Chrome:
- 将 self-signed 证书安装为 "trusted certificate authorities"
- 将 co-workers 主机添加到 Windows Internet 代理设置中作为 可信站点
- 将 co-workers 主机添加到
Software\Policies\Google\Chrome\
注册表作为
总而言之什么也没做:我仍然没有使用 Chrome 获得任何 SSO:
我试图让它在 CefSharp 中工作:
- 从
CefSharp.Handler.DefaultRequestHandler
派生,覆盖
OnSelectClientCertificate
-> 永远不会被调用
OnCertificateError
-> 不再被调用
GetAuthCredentials
-> 被调用,但我不想通过这种方式传递登录凭据 - 我已经有一个正常调用网站时 http:// 案例的有效解决方案 login-page .
- 提供 object 到
Cef.Initialize(...)
的设置,其中包含
var settings = new CefSettings { IgnoreCertificateErrors = true, ... };
settings.CefCommandLineArgs.Add ("auth-server-whitelist", "*host-url*");
settings.CefCommandLineArgs.Add ("auth-delegate-whitelist", "*host-url*");
- 在创建提供 RequestContext 的浏览器时:
var browser = new CefSharp.OffScreen.ChromiumWebBrowser (
"", requestContext: CreateNewRequestContext (webContext.Connection.Name));
<pre>CefSharp.RequestContext CreateNewRequestContext (string connName)
{
var subDirName = Helper.Files.FileHelper.MakeValidFileSystemName (connName);
var contextSettings = new RequestContextSettings
{
PersistSessionCookies = false,
PersistUserPreferences = false,
CachePath = Path.Combine (Cef.GetGlobalRequestContext ().CachePath, subDirName),
IgnoreCertificateErrors = true,
};
// ...
return new CefSharp.RequestContext (contextSettings);
}
我知道这些更改的一部分是多余的(f.e。设置白名单的 3 种方法,其中至少 2 种适用于 CefSharp,不确定影响它的注册表)以及万一IgnoreCertificateErrors
很危险,不能留在里面。我只是希望它能以某种方式工作,然后 trim 返回该怎么做才能使其在生产中工作。
研究:
- https://docs.microsoft.com/en-us/windows/desktop/SecAuthN/microsoft-ntlm
- https://www.chromium.org/developers/design-documents/http-authentication
- https://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11085 导致
- https://sysadminspot.com/windows/google-chrome-and-ntlm-auto-logon-using-windows-authentication/
- https://productforums.google.com/forum/#!msg/chrome/1594XUaOVKY/8ChGCBrwYUYJ
和其他人 .. 仍然 none 更聪明。
问题:我正在寻找救命稻草,有人在使用 CefSharp 的情况下获得了 SSO 并且可以指出我做错了什么吗?
TL;DR: 我遇到(至少)2 个问题:无效的 SSL 证书和 Kerberos 令牌问题。我的测试设置在本地计算机上设置了我调用的网络服务器。这些本地计算机大多是 windows 具有自签名证书的客户端 OS 虚拟机。有些是 windows 服务器。后者奏效了,而后者则没有。使用 IE 都可以。
使用 https://...
浏览到有问题的站点会导致 CEFsharp 遇到自签名证书(它不是受信任的证书链的一部分) - 因此它将调用浏览器 RequestHandler (如果设置)并调入其
public override bool OnCertificateError (IWebBrowser browserControl, IBrowser browser,
CefErrorCode errorCode, string requestUrl,
ISslInfo sslInfo, IRequestCallback callback)
{
Log.Logger.Warn (sslInfo.CertStatus.ToString ());
Log.Logger.Warn (sslInfo.X509Certificate.Issuer);
if (CertIsTrustedEvenIfInvalid (sslInfo.X509Certificate))
{
Log.Logger.Warn ("Trusting: " + sslInfo.X509Certificate.Issuer);
if (!callback.IsDisposed)
using (callback)
{
callback?.Continue (true);
}
return true;
}
else
{
return base.OnCertificateError (browserControl, browser, errorCode, requestUrl,
sslInfo, callback);
}
}
出于测试目的,我将某些测试硬编码到 CertIsTrustedEvenIfInvalid (sslInfo.X509Certificate)
中,这将 return true
用于我的测试环境 - 这可能会被简单的 return false
、UI-弹出窗口显示证书并询问用户是否要继续,或者它可能会考虑某些用户提供的证书文件 - 还不知道:
bool CertIsTrustedEvenIfInvalid (X509Certificate certificate)
{
var debug = new Dictionary<string, HashSet<string>> (StringComparer.OrdinalIgnoreCase)
{
["cn"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "some", "data" },
["ou"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "other", "stuff" },
["o"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "..." },
["l"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Atlantis" },
["s"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Outer Space" },
["c"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "whatsnot" },
};
var x509issuer = certificate.Issuer
.Split (",".ToCharArray ())
.Select (part => part.Trim().Split("=".ToCharArray(), 2).Select (p => p.Trim()))
.ToDictionary (t => t.First (), t => t.Last ());
return x509issuer.All (kvp => debug.ContainsKey (kvp.Key) &&
debug[kvp.Key].Contains (kvp.Value));
}
只有 SSL-Step 有效,才会尝试 SSO。
解决手头的 SSL 问题后,我 运行 进入 Chrome 与 IE/Firefox 等的不同行为,如 此处所述@选择身份验证方案
- 它的要点是:
- 如果服务器报告了多个身份验证方案,IE/Firefox 使用他们知道的第一个 - 由服务器提供(按顺序优先)
- Chrome 使用它认为最高优先级的那个(顺序:
Negotiate
-> NTLM
-> Digest
->Basic
)忽略备用方案的服务器顺序。
我的服务器报告 NTLM,Negotiante
(该命令)- 使用 IE 它很简单。
使用 Chrome 这导致交换 Kerberos 令牌 - 这仅在网络服务器托管在 Windows 服务器 OS 上时有效 - 不适用于 Windows客户 OS。可能是 AD 中使用的 Client-OS 计算机的某种失败配置。虽然不确定 - 但针对服务器 OS 它有效。
另外我实现了
public override bool GetAuthCredentials (IWebBrowser browserControl, IBrowser browser,
IFrame frame, bool isProxy, string host,
int port, string realm, string scheme,
IAuthCallback callback)
{
// pseudo code - asks for user & pw
(string UserName, string Password) = UIHelper.UIOperation (() =>
{
// UI to ask for user && password:
// return (user,pw) if input ok else return (null,null)
});
if (UserName.IsSet () && Password.IsSet ())
{
if (!callback.IsDisposed)
{
using (callback)
{
callback?.Continue (UserName, Password);
}
return true;
}
}
return base.GetAuthCredentials (browserControl, browser, frame, isProxy,
host, port, realm, scheme, callback);
}
允许在 SSO 失败时进行故障恢复。在此对话框中提供 AD 凭据后,也可以登录)。
为了更好地衡量,我还在创建新浏览器时将主机列入了 CEF 浏览器上下文的白名单,如下所示:
CefSharp.RequestContext CreateNewRequestContext (string subDirName, string host,
WebConnectionType conType)
{
var contextSettings = new RequestContextSettings
{
PersistSessionCookies = false,
PersistUserPreferences = false,
CachePath = Path.Combine (Cef.GetGlobalRequestContext ().CachePath, subDirName),
};
var context = new CefSharp.RequestContext (contextSettings);
if (conType == WebConnectionType.Negotiate) # just an enum for UserPW + Negotiate
Cef.UIThreadTaskFactory.StartNew (() =>
{
// see https://cs.chromium.org/chromium/src/chrome/common/pref_names.cc for names
var settings = new Dictionary<string, string>
{
["auth.server_whitelist"] = $"*{host}*",
["auth.negotiate_delegate_whitelist"] = $"*{host}*",
// only set-able via policies/registry :/
// ["auth.schemes"] = "ntlm" // "basic", "digest", "ntlm", "negotiate"
};
// set the settings - we *trust* the host with this and allow negotiation
foreach (var s in settings)
if (!context.SetPreference (s.Key, s.Value, out var error))
Log.Logger.Debug?.Log ($"Error setting '{s.Key}': {error}");
});
return context;
}
TL;DR: 我正在寻找救命稻草,任何人都在使用 CefSharp 的情况下获得了 SSO,并且可以指出我做错了什么?我尝试通过 CefSharp 连接到 SSL-SSO 页面,但它不起作用 - 在 Chrome-Browser 中也不起作用。对于 IE,它 可以正常工作 。我将其添加到受信任的站点 (Proxy/Security),我尝试在注册表中将 whitelist-policy URL 用于 chrome,并尝试了不同的 CefSharp 设置 - 没有任何帮助。
我正在尝试(无济于事)通过 CefSharp-Offline
-浏览连接到启用 SSO 的页面。
用普通IE浏览正常:
- 我得到 302 个答案
- 重定向的网站给我一个 401(未授权)
NTLM, Negotiate
- IE 自动发送
NTLM Auth
并接收NTLM WWW-Authenticate
- 再过一些 302 后,它以 200 结束,并在网站上显示登录状态
使用 Chrome 69.0.3497.100 浏览失败:
我想这可能是因为网络服务器是在 co-workers PC 上设置的并且使用了 self-signed 证书。
F12-在IE/Chrome中调试:
在 IE 中,我看到一个 302,然后是两个 401 答案,最后在登录站点上结束。
在 chrome 中,我只看到 302 和 200 个答案,并在 "fallback" 登录站点上结束 user/pw 条目。
(302 之一)请求 headers 的主要区别是 NEGOTIATE
与 NTLM
// IE:
Authorization: NTLM TlRMT***==
// Chrome:
Authorization: Negotiate TlRMT***==
Upgrade-Insecure-Requests: 1
DNT: 1
到目前为止,我无法通过 CefSharp 进行连接,我只是登陆了它 RequestHandler.GetAuthCredentials()
- 我不想通过它传递任何凭据。
我试图让它在内部工作的内容 Windows / Chrome:
- 将 self-signed 证书安装为 "trusted certificate authorities"
- 将 co-workers 主机添加到 Windows Internet 代理设置中作为 可信站点
- 将 co-workers 主机添加到
Software\Policies\Google\Chrome\
注册表作为
总而言之什么也没做:我仍然没有使用 Chrome 获得任何 SSO:
我试图让它在 CefSharp 中工作:
- 从
CefSharp.Handler.DefaultRequestHandler
派生,覆盖OnSelectClientCertificate
-> 永远不会被调用OnCertificateError
-> 不再被调用GetAuthCredentials
-> 被调用,但我不想通过这种方式传递登录凭据 - 我已经有一个正常调用网站时 http:// 案例的有效解决方案 login-page .
- 提供 object 到
Cef.Initialize(...)
的设置,其中包含
var settings = new CefSettings { IgnoreCertificateErrors = true, ... };
settings.CefCommandLineArgs.Add ("auth-server-whitelist", "*host-url*");
settings.CefCommandLineArgs.Add ("auth-delegate-whitelist", "*host-url*");
- 在创建提供 RequestContext 的浏览器时:
var browser = new CefSharp.OffScreen.ChromiumWebBrowser (
"", requestContext: CreateNewRequestContext (webContext.Connection.Name));
<pre>CefSharp.RequestContext CreateNewRequestContext (string connName)
{
var subDirName = Helper.Files.FileHelper.MakeValidFileSystemName (connName);
var contextSettings = new RequestContextSettings
{
PersistSessionCookies = false,
PersistUserPreferences = false,
CachePath = Path.Combine (Cef.GetGlobalRequestContext ().CachePath, subDirName),
IgnoreCertificateErrors = true,
};
// ...
return new CefSharp.RequestContext (contextSettings);
}
我知道这些更改的一部分是多余的(f.e。设置白名单的 3 种方法,其中至少 2 种适用于 CefSharp,不确定影响它的注册表)以及万一IgnoreCertificateErrors
很危险,不能留在里面。我只是希望它能以某种方式工作,然后 trim 返回该怎么做才能使其在生产中工作。
研究:
- https://docs.microsoft.com/en-us/windows/desktop/SecAuthN/microsoft-ntlm
- https://www.chromium.org/developers/design-documents/http-authentication
- https://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11085 导致
- https://sysadminspot.com/windows/google-chrome-and-ntlm-auto-logon-using-windows-authentication/
- https://productforums.google.com/forum/#!msg/chrome/1594XUaOVKY/8ChGCBrwYUYJ
和其他人 .. 仍然 none 更聪明。
问题:我正在寻找救命稻草,有人在使用 CefSharp 的情况下获得了 SSO 并且可以指出我做错了什么吗?
TL;DR: 我遇到(至少)2 个问题:无效的 SSL 证书和 Kerberos 令牌问题。我的测试设置在本地计算机上设置了我调用的网络服务器。这些本地计算机大多是 windows 具有自签名证书的客户端 OS 虚拟机。有些是 windows 服务器。后者奏效了,而后者则没有。使用 IE 都可以。
使用 https://...
浏览到有问题的站点会导致 CEFsharp 遇到自签名证书(它不是受信任的证书链的一部分) - 因此它将调用浏览器 RequestHandler (如果设置)并调入其
public override bool OnCertificateError (IWebBrowser browserControl, IBrowser browser,
CefErrorCode errorCode, string requestUrl,
ISslInfo sslInfo, IRequestCallback callback)
{
Log.Logger.Warn (sslInfo.CertStatus.ToString ());
Log.Logger.Warn (sslInfo.X509Certificate.Issuer);
if (CertIsTrustedEvenIfInvalid (sslInfo.X509Certificate))
{
Log.Logger.Warn ("Trusting: " + sslInfo.X509Certificate.Issuer);
if (!callback.IsDisposed)
using (callback)
{
callback?.Continue (true);
}
return true;
}
else
{
return base.OnCertificateError (browserControl, browser, errorCode, requestUrl,
sslInfo, callback);
}
}
出于测试目的,我将某些测试硬编码到 CertIsTrustedEvenIfInvalid (sslInfo.X509Certificate)
中,这将 return true
用于我的测试环境 - 这可能会被简单的 return false
、UI-弹出窗口显示证书并询问用户是否要继续,或者它可能会考虑某些用户提供的证书文件 - 还不知道:
bool CertIsTrustedEvenIfInvalid (X509Certificate certificate)
{
var debug = new Dictionary<string, HashSet<string>> (StringComparer.OrdinalIgnoreCase)
{
["cn"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "some", "data" },
["ou"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "other", "stuff" },
["o"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "..." },
["l"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Atlantis" },
["s"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Outer Space" },
["c"] = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "whatsnot" },
};
var x509issuer = certificate.Issuer
.Split (",".ToCharArray ())
.Select (part => part.Trim().Split("=".ToCharArray(), 2).Select (p => p.Trim()))
.ToDictionary (t => t.First (), t => t.Last ());
return x509issuer.All (kvp => debug.ContainsKey (kvp.Key) &&
debug[kvp.Key].Contains (kvp.Value));
}
只有 SSL-Step 有效,才会尝试 SSO。
解决手头的 SSL 问题后,我 运行 进入 Chrome 与 IE/Firefox 等的不同行为,如 此处所述@选择身份验证方案 - 它的要点是:
- 如果服务器报告了多个身份验证方案,IE/Firefox 使用他们知道的第一个 - 由服务器提供(按顺序优先)
- Chrome 使用它认为最高优先级的那个(顺序:
Negotiate
->NTLM
->Digest
->Basic
)忽略备用方案的服务器顺序。
我的服务器报告 NTLM,Negotiante
(该命令)- 使用 IE 它很简单。
使用 Chrome 这导致交换 Kerberos 令牌 - 这仅在网络服务器托管在 Windows 服务器 OS 上时有效 - 不适用于 Windows客户 OS。可能是 AD 中使用的 Client-OS 计算机的某种失败配置。虽然不确定 - 但针对服务器 OS 它有效。
另外我实现了
public override bool GetAuthCredentials (IWebBrowser browserControl, IBrowser browser,
IFrame frame, bool isProxy, string host,
int port, string realm, string scheme,
IAuthCallback callback)
{
// pseudo code - asks for user & pw
(string UserName, string Password) = UIHelper.UIOperation (() =>
{
// UI to ask for user && password:
// return (user,pw) if input ok else return (null,null)
});
if (UserName.IsSet () && Password.IsSet ())
{
if (!callback.IsDisposed)
{
using (callback)
{
callback?.Continue (UserName, Password);
}
return true;
}
}
return base.GetAuthCredentials (browserControl, browser, frame, isProxy,
host, port, realm, scheme, callback);
}
允许在 SSO 失败时进行故障恢复。在此对话框中提供 AD 凭据后,也可以登录)。
为了更好地衡量,我还在创建新浏览器时将主机列入了 CEF 浏览器上下文的白名单,如下所示:
CefSharp.RequestContext CreateNewRequestContext (string subDirName, string host,
WebConnectionType conType)
{
var contextSettings = new RequestContextSettings
{
PersistSessionCookies = false,
PersistUserPreferences = false,
CachePath = Path.Combine (Cef.GetGlobalRequestContext ().CachePath, subDirName),
};
var context = new CefSharp.RequestContext (contextSettings);
if (conType == WebConnectionType.Negotiate) # just an enum for UserPW + Negotiate
Cef.UIThreadTaskFactory.StartNew (() =>
{
// see https://cs.chromium.org/chromium/src/chrome/common/pref_names.cc for names
var settings = new Dictionary<string, string>
{
["auth.server_whitelist"] = $"*{host}*",
["auth.negotiate_delegate_whitelist"] = $"*{host}*",
// only set-able via policies/registry :/
// ["auth.schemes"] = "ntlm" // "basic", "digest", "ntlm", "negotiate"
};
// set the settings - we *trust* the host with this and allow negotiation
foreach (var s in settings)
if (!context.SetPreference (s.Key, s.Value, out var error))
Log.Logger.Debug?.Log ($"Error setting '{s.Key}': {error}");
});
return context;
}