如何获取当前登录用户的凭据(NetworkCredential)?

32

我正在编写一些代码,以利用第三方组件,并且在开始使用它时需要提供一个实现了 ICredentials 接口的对象。

如果我编写以下代码...

var credential = new NetworkCredential("MyUsername", "MyPassword");

如果我只传递“credential”,那就没问题。但我想传递当前用户的凭据(它是一个Windows服务,因此作为指定用户运行)

我尝试了以下两种方法,但似乎都不起作用(或者没有返回任何内容)

NetworkCredential credential = System.Net.CredentialCache.DefaultCredentials;
NetworkCredential credential = CredentialCache.DefaultNetworkCredentials;

有人能建议如何获取一个适当的对象,代表运行服务的用户名的凭据吗?

谢谢


CredentialCache 应该可以工作。你能检查一下 WindowsIdentity.GetCurrent 并确认是否真的有用户登录了吗? - Simon Mourier
3
你好,WindowsIdentity.GetCurrent返回一个WindowsIdentity对象(包含当前用户名),但是System.Net.CredentialCache.DefaultCredentials和DefaultNetworkCredentials两者都返回空的ICredentials对象。 - Black Light
你们的第三方组件是什么?它支持NTLM或Kerberos之类的东西吗?答案不会是尝试读取用户的密码——那将是一个明显的安全漏洞。你需要找到一种不同的身份验证方式。 - Mark Brackett
NetworkCredential 对象是一个用于保存用户名和密码的对象。如果你想将应用程序的功能传递给另一个进程,那么 NetworkCredential 对象并不是实现这一目的的方式。 - Ross Presser
啊……我明白了你的意思。NetworkCredential并不是一种安全上下文对象("当前"实例可能从某个地方获取),而更像是一个包含用户名和密码的容器。因此,某些假设的“当前”实例将具有当前的用户名和密码,因此不存在。我可以理解为什么会这样,但第三方使用它有点设计不良。再次感谢。 - Black Light
显示剩余4条评论
6个回答

2

你尝试过使用 WindowsIdentity.GetCurrent 吗? 是的,它似乎没有帮助 - 即使将结果传递到 Impersonate 中。 这个例子似乎只是一个有趣(?)的获取当前用户名的方式。谢谢。 - Black Light

0

你需要进行模拟身份,例如:

    System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Insert your code that runs under the security context of the authenticating user here.

impersonationContext.Undo();

http://support.microsoft.com/kb/306158

或者您可以使用 web.config 文件:

<identity impersonate="true" />

2
谢谢,但我是作为Windows服务运行的,而不是作为ASP网页。到目前为止,我找到的所有建议都与ASP相关。我已经尝试了模拟身份,但在这种情况下它没有帮助/工作。我很惊讶似乎没有办法获取当前用户的凭据(毕竟已登录),而必须编写一些hacky方法来存储用户的用户名和密码。Yuk!(感谢您的建议) - Black Light

0

理想的安全情况是,已登录用户的密码不会存储在内存中的任何位置。它也不会存储在磁盘上的任何位置。它仅存在于哈希值中,以与人类输入的字符串进行比较。明文存储密码本质上是一种安全风险,应尽可能避免。

基于这个原则,操作系统中甚至没有任何部分以明文形式保存您的用户密码,更不用说愿意将其提供给您了。


5
这里似乎有些混淆。我从未问过如何获取密码。我询问的是,考虑到我有一个必须已经被“登录”(用更好的术语来说)的进程正在使用有效凭据运行,我想将这些凭据传递给第三方组件-我不需要知道它们是什么。我知道如果我创建了一组新的凭据(假设我知道密码),它会起作用,但我找不到一种方法来获取(并传递)当前的凭据。 - Black Light
这正是我所描述的情况。要获取当前凭据,它们必须由某个软件持有。这将降低系统的安全性。模拟应该允许您希望调用的任何组件“扮演”已登录的用户,而无需实际凭据。我不确定为什么您没有对此帖子的第一个答案进行投票,该答案对安全性做出了相同的声明(“事实上,这是一种不安全的做法”)。 - Ross Presser
1
拥有代表当前进程凭证的签名令牌(允许执行某些操作,包括像进程本身一样与其他程序通信)并不等同于拥有凭证。由于进程之间可能存在多种通信方式,因此这是可配置的。将此令牌作为参数传递是指定我们要进行身份验证“以自己的身份”而不使用新凭证的预期方式。这就是我们试图做的全部内容。 - Jason Kleban
1
按照定义,NetworkCredential需要用户名和密码。理论上可能存在一种不需要用户名和密码的iCredential,并且可以提供给第三方组件使用。但我找不到这样的组件。 - Ross Presser

0
你尝试过在应用程序启动时设置应用程序域的PrincipalPolicy吗?
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);

在通过线程访问当前主体对象之前设置此值,以确保该对象中使用了 Windows 身份验证。

编辑-我很确定这适用于 DefaultNetworkCredentials。我用它从 Windows 窗体应用程序访问启用了 Windows 认证的 Web 服务。


0

-2

如果你只想以当前用户身份运行进程,添加动词:

"runas " & Environment.UserName

如果你想以管理员身份运行进程,只需写入 "runas"

在vb.net中

Dim ps As New System.Diagnostics.ProcessStartInfo("filepath", "arguments")

ps.Verb = "runas" 'run as admin

'ps.Verb = "runas " & Environment.UserName'run as current user, by default

Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(ps)

如果您想获取当前用户的密码,实际上这是一种不安全的做法。您的服务需要以什么权限和目的来获取我的Windows密码?例如,这就像将您手机的PIN码提供给WhatsApp一样。


1
这不回答问题。 - MgSam

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