在控制台应用程序中使用默认凭据调用 API

4
我正在尝试从我的桌面运行的控制台应用程序调用需要授权的Web API 2方法,但我收到了401未经授权的错误。我知道我有授权,因为当我从Web浏览器进行相同的调用时,它可以正常工作。所以浏览器可以获取我的默认登录ID /密码并发送到API,但.NET的WebClient不能?这似乎很荒谬。必须有一种方法在不输入我的ID /密码的情况下完成此操作。

以下是我在控制台应用程序中使用的代码,但它无法正常工作。

这是使用Windows身份验证的内部网络内容。

这会抛出异常“远程服务器返回错误:(401)未经授权”。

using(var c = new WebClient())
{
    c.UseDefaultCredentials = true;   
    string value = c.DownloadString("http://localhost:62659/api/Store/GetData");
}

我也尝试过以下操作,当我将鼠标悬停在DefaultNetworkCredentials上时,用户名/密码是空字符串。为什么.NET不能弄清楚这一点呢?

using(var c = new WebClient())
            {
                var creds = new CredentialCache();
                var uri = new Uri("http://localhost:62659/api/Store/GetData");
                creds.Add(uri, "ntlm", System.Net.CredentialCache.DefaultNetworkCredentials);
                c.Credentials = creds;
                string value = c.DownloadString(uri);
            }

你是否收到了异常或任何错误信息可以分享? - gmiley
Fiddler2会显示与GET请求一起传递的凭据。 - samus
我使用 Postman 来解决这类问题。 - jomsk1e
您能够在监控网络流量时查看凭据信息并在两个不同的调用之间进行比较吗? - gmiley
你的登录信息是否存储在凭据管理器中?Chrome很可能已经保存了你的凭据信息,但是你没有将这些信息保存在Windows中。请在“控制面板 > 凭据管理器”中查找这些凭据信息。 - gmiley
显示剩余5条评论
2个回答

4
很有可能您没有将凭据信息存储在Windows凭据管理器中。您可以通过控制面板>凭据管理器访问该信息。从那里,您可以添加所需的任何凭据。CredentialCache.DefaultCredentialsCredentialCache.DefaultNetworkCredentials包含当前登录或模拟用户的登录凭据。如果您连接的内容需要不同的凭据,则这些凭据将无法使用。您需要将这些凭据添加到Windows的凭据管理器中。
您能够在Chrome中正常连接的原因是Chrome会在自身内部存储您指定要保存的凭据。
将登录凭据用作功能ID时,可以设置永不过期,或者需要将其添加到每月/每年维护项目列表中以更新这些帐户的密码。
您还需要处理应用程序中使用错误的登录信息。如果这是一个自动化任务,请让它通过电子邮件或其他方式通知某人需要更新凭据。
如果用户运行此操作,则可以简单地提示当前用户提供新密码,然后立即使用该密码更新存储的凭据。

另一种选择是使用相同的凭据将运行应用程序的用户设置为接收端的用户。这样,整个过程都与将运行应用程序的用户相关联。


这真是个大麻烦。在公司设置中,当应用程序从批处理服务器运行时,管理员不会想在更改批处理ID / PW(我们在调度系统中创建作业时不知道)时维护它。真是个大麻烦。 - user441521
@user441521 - 在看到你上面的评论后,我稍微提到了一点。另一种方法是将此写入您的应用程序中。如果凭据因错误的登录信息而失败,您可以通过电子邮件或其他方式通知某人,需要更新凭据。 - gmiley
@user441521 - 我已经扩展了我的答案,希望能提供一些替代方案。 - gmiley
@user441521 - 这些内容对你回答问题有帮助吗? - gmiley
这将从调度系统中调用,因此只有管理员维护的1个用户。我认为没有任何绕过这个的方法。我很可能会创建一个控制台应用程序,使用Windows身份验证直接访问数据库,并执行与API相同的SQL操作。 - user441521
@user441521 - 这是你可以与网络管理员讨论的事情,但我曾与很多使用自动化设置中这种设计的人/公司进行过讨论,他们将正在使用的帐户设置为永不过期。 然后将它们添加到帐户列表中,并可以将其添加到计划中,作为管理员定期维护计划的一部分更改其密码,而不是在白天或更糟糕的是在半夜时帐户过期的可能性。 - gmiley

1

使用DefaultCredentials应该可以在控制台应用程序中使用Windows身份验证。只要您拥有Web API正在寻找的适当授权标头即可。与我的评论相同,我建议使用Postman测试api调用,以便您可以进行故障排除并检查您所缺少的内容。

关于凭据为空的问题,这可能是因为您正在使用DefaultNetworkCredentials。

尝试这个:

using(var c = new WebClient())
{
    var uri = new Uri("http://localhost:62659/api/Store/GetData");
    c.Credentials = System.Net.CredentialCache.DefaultCredentials;
    string value = c.DownloadString(uri);
}

如果您想使用NetworkCredential,您需要像这样输入网络凭据:
c.Credentials = new NetworkCredential(username, password, domain);

我创建了这种类型的控制台应用程序并将其用作服务,我可以告诉你这应该是有效的。您只需要逐步排除故障并找到真正的问题即可。

NetworkCredential和DefaultCredentials有什么区别?我的ID应该是DefaultCredentials,我想,在网络上是一个AD ID。不幸的是,我的地方不允许我运行Postman。尝试使用Fiddler但没有看到流量出现,但我并不经常使用Fiddler,所以可能是我自己的问题。还在尝试中。你使用的Web API是带有控制器上Authorize标记并使用Windows身份验证的Web API 2吗? - user441521
Fiddler似乎无法显示来自控制台应用程序的内容。 - user441521
@user441521 - DefaultNetworkCredentialsNetworkCredential 类型的实际类。DefaultCredentials 返回 ICredentials 类型的对象,但是 DefaultCredentials 上的 GetCredential() 函数返回 NetworkCredential 类型的对象。无论你使用哪个,你实际上都在使用实现了 ICredentials 接口的 NetworkCredential 实例。 - gmiley
Fiddler有一个composer选项卡,允许我从那里进行调用。它有一个自动身份验证选项。我勾选它并运行此URL,但仍然得到相同的401错误。它的Auth选项卡显示:Authorization Header(Negotiate)似乎包含一个Kerberos票证,然后是一些十六进制内容。 - user441521
https://weblog.west-wind.com/posts/2010/feb/18/net-webrequestpreauthenticate-not-quite-what-it-sounds-like - jomsk1e
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接