当连接到当前用户(在我的例子中,是启用网络的服务用户)没有权限的网络共享时,必须提供名称和密码。
我知道如何用Win32函数(来自mpr.dll的WNet*家族)做到这一点,但想用. net(2.0)功能。
有哪些选择?
也许更多的信息会有所帮助:
用例是一个windows服务,而不是一个Asp。网络应用程序。 该服务运行在一个没有共享权限的帐户下。 客户端不知道共享所需的用户帐户。 客户端和服务器不是同一域的成员。
当连接到当前用户(在我的例子中,是启用网络的服务用户)没有权限的网络共享时,必须提供名称和密码。
我知道如何用Win32函数(来自mpr.dll的WNet*家族)做到这一点,但想用. net(2.0)功能。
有哪些选择?
也许更多的信息会有所帮助:
用例是一个windows服务,而不是一个Asp。网络应用程序。 该服务运行在一个没有共享权限的帐户下。 客户端不知道共享所需的用户帐户。 客户端和服务器不是同一域的成员。
当前回答
好吧……我可以回应…
免责声明:我刚刚(又)一天工作了18个多小时。我老了,健忘了。我不会拼写。我的注意力持续时间很短,所以我最好快速反应。: -)
问题:
是否可以将线程主体更改为在本地机器上没有帐户的用户?
答:
是的,您可以更改线程主体,即使您使用的凭据没有在本地定义或在“林中”之外。
我刚刚在尝试从服务使用NTLM身份验证连接到SQL服务器时遇到了这个问题。此调用使用与流程关联的凭据,这意味着在进行模拟之前需要通过本地帐户或域帐户进行身份验证。之类的……
但是…
调用属性为????的LogonUser(..)_NEW_CREDENTIALS将返回一个安全令牌,而不尝试验证凭据。酷. .不必在“森林”中定义帐户。获得令牌后,您可能必须调用DuplicateToken(),并使用选项启用模拟,从而生成一个新的令牌。现在调用SetThreadToken(NULL, token);(可能是&token?)..调用ImpersonateLoggedonUser(令牌);可能是必需的,但我不这么认为。查一下…
做你该做的。
调用RevertToSelf()如果你调用了ImpersonateLoggedonUser()然后SetThreadToken(NULL, NULL);(我认为…然后在创建的句柄上使用CloseHandle() ..
没有保证,但这对我很有效……这是在我的头顶(就像我的头发),我不会拼写!!
其他回答
一种可行的方法是使用WindowsIdentity。模拟(并更改线程主体)成为所需的用户,如下所示。回到p/invoke,不过,恐怕……
另一个厚脸皮的(同样不理想的)选择可能是生成一个流程来完成这项工作……ProcessStartInfo接受. username, . password和. domain。
最后-也许在一个有权限的专用帐户中运行服务?(删除,因为你已经澄清这不是一个选项)。
如果你不能创建一个本地有效的安全令牌,似乎你已经排除了所有选项栏Win32 API和WNetAddConnection*。
MSDN上关于WNet - PInvoke信息和连接到UNC路径的示例代码的大量信息:
http://www.pinvoke.net/default.aspx/mpr/WNetAddConnection2.html#
MSDN参考:
http://msdn.microsoft.com/en-us/library/aa385391 (VS.85) . aspx
也移植到f#使用FAKE
module NetworkShare
open System
open System.ComponentModel
open System.IO
open System.Net
open System.Runtime.InteropServices
type ResourceScope =
| Connected = 1
| GlobalNetwork = 2
| Remembered = 3
| Recent = 4
type ResourceType =
| Any = 0
| Disk = 1
| Print = 2
| Reserved = 8
type ResourceDisplayType =
| Generic = 0x0
| Domain = 0x01
| Server = 0x02
| Share = 0x03
| File = 0x04
| Group = 0x05
| Network = 0x06
| Root = 0x07
| Shareadmin = 0x08
| Directory = 0x09
| Tree = 0x0a
| Ndscontainer = 0x0b
//Uses of this construct may result in the generation of unverifiable .NET IL code.
#nowarn "9"
[<StructLayout(LayoutKind.Sequential)>]
type NetResource =
struct
val mutable Scope : ResourceScope
val mutable ResourceType : ResourceType
val mutable DisplayType : ResourceDisplayType
val mutable Usage : int
val mutable LocalName : string
val mutable RemoteName : string
val mutable Comment : string
val mutable Provider : string
new(name) = {
// lets preset needed fields
NetResource.Scope = ResourceScope.GlobalNetwork
ResourceType = ResourceType.Disk
DisplayType = ResourceDisplayType.Share
Usage = 0
LocalName = null
RemoteName = name
Comment = null
Provider = null
}
end
type WNetConnection(networkName : string, credential : NetworkCredential) =
[<Literal>]
static let Mpr = "mpr.dll"
[<DllImport(Mpr, EntryPoint = "WNetAddConnection2")>]
static extern int connect(NetResource netResource, string password, string username, int flags)
[<DllImport(Mpr, EntryPoint = "WNetCancelConnection2")>]
static extern int disconnect(string name, int flags, bool force)
let mutable disposed = false;
do
let userName = if String.IsNullOrWhiteSpace credential.Domain
then credential.UserName
else credential.Domain + "\\" + credential.UserName
let resource = new NetResource(networkName)
let result = connect(resource, credential.Password, userName, 0)
if result <> 0 then
let msg = "Error connecting to remote share " + networkName
new Win32Exception(result, msg)
|> raise
let cleanup(disposing:bool) =
if not disposed then
disposed <- true
if disposing then () // TODO dispose managed resources here
disconnect(networkName, 0, true) |> ignore
interface IDisposable with
member __.Dispose() =
disconnect(networkName, 0, true) |> ignore
GC.SuppressFinalize(__)
override __.Finalize() = cleanup(false)
type CopyPath =
| RemotePath of string * NetworkCredential
| LocalPath of string
let createDisposable() =
{
new IDisposable with
member __.Dispose() = ()
}
let copyFile overwrite destPath srcPath : unit =
use _srcConn =
match srcPath with
| RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
| LocalPath(_) -> createDisposable()
use _destConn =
match destPath with
| RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
| LocalPath(_) -> createDisposable()
match srcPath, destPath with
| RemotePath(src, _), RemotePath(dest, _)
| LocalPath(src), RemotePath(dest, _)
| RemotePath(src, _), LocalPath(dest)
| LocalPath(src), LocalPath(dest) ->
if FileInfo(src).Exists |> not then
failwith ("Source file not found: " + src)
let destFilePath =
if DirectoryInfo(dest).Exists then Path.Combine(dest, Path.GetFileName src)
else dest
File.Copy(src, destFilePath, overwrite)
let rec copyDir copySubDirs filePattern destPath srcPath =
use _srcConn =
match srcPath with
| RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
| LocalPath(_) -> createDisposable()
use _destConn =
match destPath with
| RemotePath(path, credential) -> new WNetConnection(path, credential) :> IDisposable
| LocalPath(_) -> createDisposable()
match srcPath, destPath with
| RemotePath(src, _), RemotePath(dest, _)
| LocalPath(src), RemotePath(dest, _)
| RemotePath(src, _), LocalPath(dest)
| LocalPath(src), LocalPath(dest) ->
let dir = DirectoryInfo(src)
if dir.Exists |> not then
failwith ("Source directory not found: " + src)
let dirs = dir.GetDirectories()
if Directory.Exists(dest) |> not then
Directory.CreateDirectory(dest) |> ignore
let files = dir.GetFiles(filePattern)
for file in files do
let tempPath = Path.Combine(dest, file.Name)
file.CopyTo(tempPath, false) |> ignore
if copySubDirs then
for subdir in dirs do
let subdirSrc =
match srcPath with
| RemotePath(_, credential) -> RemotePath(Path.Combine(dest, subdir.Name), credential)
| LocalPath(_) -> LocalPath(Path.Combine(dest, subdir.Name))
let subdirDest =
match destPath with
| RemotePath(_, credential) -> RemotePath(subdir.FullName, credential)
| LocalPath(_) -> LocalPath(subdir.FullName)
copyDir copySubDirs filePattern subdirDest subdirSrc
好吧……我可以回应…
免责声明:我刚刚(又)一天工作了18个多小时。我老了,健忘了。我不会拼写。我的注意力持续时间很短,所以我最好快速反应。: -)
问题:
是否可以将线程主体更改为在本地机器上没有帐户的用户?
答:
是的,您可以更改线程主体,即使您使用的凭据没有在本地定义或在“林中”之外。
我刚刚在尝试从服务使用NTLM身份验证连接到SQL服务器时遇到了这个问题。此调用使用与流程关联的凭据,这意味着在进行模拟之前需要通过本地帐户或域帐户进行身份验证。之类的……
但是…
调用属性为????的LogonUser(..)_NEW_CREDENTIALS将返回一个安全令牌,而不尝试验证凭据。酷. .不必在“森林”中定义帐户。获得令牌后,您可能必须调用DuplicateToken(),并使用选项启用模拟,从而生成一个新的令牌。现在调用SetThreadToken(NULL, token);(可能是&token?)..调用ImpersonateLoggedonUser(令牌);可能是必需的,但我不这么认为。查一下…
做你该做的。
调用RevertToSelf()如果你调用了ImpersonateLoggedonUser()然后SetThreadToken(NULL, NULL);(我认为…然后在创建的句柄上使用CloseHandle() ..
没有保证,但这对我很有效……这是在我的头顶(就像我的头发),我不会拼写!!
你应该像这样添加一行:
<identity impersonate="true" userName="domain\user" password="****" />
在你的web.config中。
更多的信息。