在Windows上,是否可以将单个goroutine作为不同的用户运行?

huangapple go评论93阅读模式
英文:

On windows, is it possible to run a single goroutine as a different user?

问题

如何将一个goroutine的运行委托给Windows上的另一个非管理员帐户?我看到在Linux上可以使用syscall.Setuid()来实现这一点。但是我无法找到在Windows上使用Windows syscall包来实现这一点的方法。我希望能够在程序运行时设置goroutine所在的帐户。这种可能吗?

背景信息:我想切换运行goroutine的用户,这样我就可以在使用go-oci8时更改传递给Oracle的操作系统用户的数据库连接(请参阅我的其他问题)。我需要连接到数据库,它使用已登录的用户(操作系统用户)作为安全的一部分。在Java中,我可以在连接设置期间更改环境变量(或者如果只连接一个用户,则切换用户名环境变量)。

我有用户的数据库用户名(与操作系统用户名匹配),并且我获得了数据库用户密码。我没有用户的Windows登录密码。我希望能够从以管理员身份运行的主要go程序中将运行goroutine的权限委托给所需的Windows用户,就像我提到的Linux端口绑定示例一样。不使用操作系统用户进行Oracle登录不是一个选项,所以如果我无法解决这个问题,我将回到Java :-(。

英文:

How do you delegate the running of a goroutine to another non administrator account on windows? I see you can do this on Linux using syscall.Setuid(). I can't see how to do this on Windows using the windows syscall package. I'd like to be able to set the account the goroutine runs under while the program is running. Is this possible?

Bit of background :- I want to switch the user that runs the goroutine so I can change the OS User passed to Oracle during the database connection when I use go-oci8 (See my other question). I need to connect to the database and it uses the logged in user (OS User) as part of the security. In java I can change the environment variable during connection set up (or flick the username environmental variable if only connecting for a single user).

I have the users database username (this matches the OS user name) and I get the database user password. I don't have the users windows login password. I was hoping to be able to delegate running a goroutine to the required windows user from the main go program running as admin in a similar way to Linux port binding example I highlighted. Changing the Oracle login to not use OS User is not an option so it will be back to Java if I can't work it out 在Windows上,是否可以将单个goroutine作为不同的用户运行? .

答案1

得分: 7

理论上来说,不可能实现,因为在Linux和Windows上,用户身份的概念仅适用于操作系统级别的线程,而goroutine不是操作系统线程,而是非常轻量级的实体,由Go调度器(Go运行时内置的一部分)映射到真正的操作系统线程上,在其生命周期中,goroutine可能在不同的操作系统线程上的不同时间执行。

但是,存在一种类似于“退出通道”的机制,最初设计用于帮助调用C代码:runtime.LockOSThread()。一旦一个goroutine调用了这个函数,它就会被固定在当前正在运行的线程上,并且无论如何都不会被调度到其他线程上,直到goroutine退出或调用runtime.UnlockOSThread()

你可以像这样使用它:

go func() {
  runtime.LockOSThread()
  defer runtime.UnlockOSThread()
  impersonate() // 获取并假扮其他凭据
  ...
}

这个想象中的impersonate()函数的实现超出了本问题的范围;你可以使用syscall包调用任何Win32 API函数,有关示例,请参阅Go标准库。

请注意,在实际场景中调用runtime.LockOSThread()会导致将一个完整的操作系统线程专用于单个goroutine(而通常许多goroutine在一个线程上运行),因此,如果你计划生成大量这样的锁定到操作系统线程的goroutine,请准备处理增加的操作系统资源使用情况。

更新:一个可工作的示例,在Windows XP Pro SP3 32位上使用Go 1.2.1/i386进行了测试。

它硬编码了用户名为“foo”,密码为“foo”的用户。要快速在Windows上创建一个用户,请执行以下操作:

net user foo * /ADD

然后在提示时两次输入密码。

英文:

In theory, no, it is not possible because both on Linux and Windows the concept of user's identity only exists for OS-level threads and goroutines are not OS threads—instead, they are very light-weight entities which are mapped to real OS threads by the Go scheduler (a part of the Go runtime built into your executable), and during its lifetime a goroutine might be executed on different OS threads at different times.

But there exist a sort of an "exit hatch" for your situation originally designed to help calling into C code: runtime.LockOSThread(). Once a goroutine calls this function it's stuck to the thread it's currently running on and won't be scheduled to be called on another no matter what until the goroutine exits or calls runtime.UnlockOSThread().

You might use this like this:

go func() {
  runtime.LockOSThread()
  defer runtime.UnlockOSThread()
  impersonate() // acquires and assumes some other credentials
  ...
}

The implementation of that imaginary impersonate() function is out of the scope of this question; you can call any Win32 API function using the syscall package—see the standard Go library for examples.


Note that calling runtime.LockOSThread() in real-world scenarious results in dedicating a whole OS thread to just a single goroutine (while usually a whole lot of them runs on just a single one) so if you plan to spawn a lot of such goroutines locked to OS threads be prepared to deal with increased OS resource usage.

Update: a working example tested on Windows XP Pro SP3 32-bit with Go 1.2.1/i386.

It hard codes the user "foo" identified by the password "foo". To quickly create a user on Windows, do

net user foo * /ADD

and type its password twice when prompted.

答案2

得分: 0

Goroutines是绿色线程,可以随意映射到各种操作系统线程。因此,你最初的假设(在Linux上可以通过简单的syscall.Setuid()实现)也可能是错误的。我认为,你需要在一个完全独立的进程中运行,以获得所需的权限限制。

英文:

Goroutines are green threads and may be mapped around to various operating system threads at will. So your original assumption (that you can do this with a simple syscall.Setuid() on linux) is also probably false. You would need to run in an entirely separate process I think to get the privilege restrictions you want.

huangapple
  • 本文由 发表于 2014年9月30日 22:23:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/26123218.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定