【问题标题】:Check if Windows Authentication is available with JavaScript检查 Windows 身份验证是否可用于 JavaScript
【发布时间】:2017-03-30 19:02:20
【问题描述】:

有没有办法检查 Windows 身份验证(协商、Kerberos、NTLM...)在浏览器中是否可用(使用 JavaScript 或其他方法),如果不是,浏览器不会提示输入用户名和密码?

背景

我们正在开发 Angular2 SPA 企业应用程序,如果可用(用户正在从加入域的计算机访问应用程序),我们希望通过 Windows 身份验证使用 SSO,如果它不可用,则优雅地故障转移到基于表单的身份验证(从Internet 或未加入域的计算机)。

设置

在服务器端有一个受 Windows 身份验证保护的资源(即 REST 方法)。当您使用 JavaScript 调用此 REST 方法时,会发生以下两种情况之一:

  1. 如果 Windows 身份验证可用,将调用方法,您将收到 200 OK 响应
  2. 如果 Windows 身份验证不可用,将返回 401 Unathorized,并将 WWW-Authenticate 标头设置为 Negotiate,这将导致浏览器(至少 IE,未在其他人中测试,但无论使用何种浏览器都需要能够检测到这一点) 显示登录提示

问题

不希望显示登录提示,我们希望优雅地退回到基于表单的登录。

一些solutions 建议从响应中删除 WWW-Authenticate 标头,但这将阻止 Windows 身份验证工作,因为此步骤是 broser-server 协商身份验证协议的一部分。如果删除,浏览器将永远不会发送 NTLM 或 Kerberos 令牌。

我们同时控制前端和后端,因此可以修改其中任何一个以使其正常工作。此外,没有 CORS,一切都是来自单个域的服务器。

任何可以从客户端检测 Windows 身份验证是否可用的方法对我们来说都足够好。到目前为止我发现的是this,但它仅适用于 IE,需要启用 ActiveX。 This 问题有点相关,但它也没有解决方案,而且很老了。

【问题讨论】:

  • 我也有同样的需求。我已经建立了 IdentityServer,它可以设置为允许用户使用表单或 NTLM 登录。 NTLM 被视为外部身份验证提供程序,用户可以单击一个按钮来使用它,或者使用登录表单(或 Google 等,如果您添加它)。但是,如果用户已加入域并启用了自动登录,我希望“Windows”按钮显示“以 DOMAIN\user 身份登录”,而当他们没有登录时不会提示登录。
  • @Daniel 我仍然没有找到解决这个问题的方法。我们很可能会按照您描述的方式实现它。我目前看不到其他可悲的方式。如果您发现有用的信息,请务必告诉我。
  • 很高兴知道我不是唯一一个 ;) 如果找到解决方案,请发布解决方案。
  • 你找到解决这个问题的方法了吗?很想知道这是否可能。谢谢!
  • @SunilJamkatel 不,我们没有。我们很可能会创建 login.domain.com 类型的 SSO,其中从内部网络 (LAN) 它将指向一个有 Windows 身份验证的站点,从 Internet 它将指向一个禁用 WA 的站点。这将阻止向外部用户显示登录提示,这已经足够了。

标签: javascript angular authentication single-sign-on windows-authentication


【解决方案1】:

我们在 Web Worker 中使用 XmlHttpRequest。 这样可以在失败时执行 Kerberos 身份验证而不触发登录窗口。

IE11支持Web Workers,所以你应该很好用。

这涉及证明一个 API 端点,您可以在其中尝试通过 Kerberos 进行身份验证,例如'yourhost.tld/krb5LoginUrl'

您的网络工作者(例如提供 task.js):

self.addEventListener('message', function(e) {

  var oReq = new XMLHttpRequest();
  oReq.addEventListener("load", reqListener);
  oReq.open("GET",  e.data);
  oReq.send(null);

  function reqListener () {
    self.postMessage(this.status);
  }, false);

在您的主应用程序代码中注册工作者: const worker = new Worker('task.js');

worker.postMessage(/krb5LoginUrl); // Sends the url to our worker and triggers xmlHttpRequest.

worker.addEventListener('message', function (e) {
  if (e.data == 200) {
    console.log("Krb5 login successful");
  } else {
    console.log("Krb5 login failed");
  }
 }, false);
}

【讨论】:

  • 这并没有让我知道我的答案有什么问题。
  • 您说“我们遇到了同样的问题”但实际上并没有给出答案(除了一个关于可能但未经测试的方法的非常笼统的句子)这一事实使人们相信......你有同样的问题。有同样的问题是“不是答案”。如果您想改进您的答案,请添加更多关于您如何解决问题的内容,并删除关于您遇到相同问题的句子。
  • @TadeusSenf 感谢您编辑您的答案,做得好,我删除 cmets 并投票。欢迎来到 SO ;)
  • @GCO 谢谢。如果有任何不清楚的地方(对于任何人),请发表评论
  • 这不适用于 Chrome(版本 80.0.3987.132(官方构建)(64 位))。如果 Kerberos 身份验证失败,仍会显示基本身份验证弹出窗口。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多