我正在使用以下代码更改文件的所有者。此代码在使用C#,4.0版编写的Windows服务中运行。它运行在运行Windows Server 2008 R2 Standard,Service Pack 1的本地服务器上。
我需要将通过FTP接收的文件的所有者更改为域帐户。我可以登录到框并使用资源管理器手动执行,但是当我尝试通过代码运行时,我得到一个InvalidOperation异常。我可以将所有者更改为本地系统帐户,但不能更改为网络帐户。任何有关这方面的帮助将不胜感激。
我正在处理一些处理EDI文件的奇怪的Microsoft Dynamics AX代码。该过程要求文件的所有者是有效的DAX用户,在这种情况下是域用户。我们有供应商通过FTP向我们发送EDI数据。我们的DAX应用程序每10分钟检查一次FTP目录并处理这些文件。该进程当前失败,因为所有者无效。所以,我写了一个服务,以便在文件到达时更改文件的所有者。但是,下面的代码失败,代码示例下面显示异常。
var ediFileOwner = new NTAccount("MyDomain", _ediEndpointUserAccount);
var fileSecurity = File.GetAccessControl(fileName);
var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
fileSecurity.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.FullControl, AccessControlType.Allow));
fileSecurity.AddAccessRule(new FileSystemAccessRule(ediFileOwner, FileSystemRights.TakeOwnership, AccessControlType.Allow));
fileSecurity.SetOwner(ediFileOwner); //Change our owner from to our desired User
File.SetAccessControl(fileName, fileSecurity);
以下是完整的例外:
System.InvalidOperationException: The security identifier is not allowed to be the owner of this object.
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle handle, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.IO.File.SetAccessControl(String path, FileSecurity fileSecurity)
更新
如果我将服务运行的帐户更改为我尝试更改为所有者的帐户,我会得到一个不同的例外。
意外异常:System.UnauthorizedAccessException:试图 执行未经授权的操作。在 System.Security.AccessControl.Win32.SetSecurityInfo(ResourceType类型, 字符串名称,SafeHandle句柄,SecurityInfos securityInformation, SecurityIdentifier所有者,SecurityIdentifier组,GenericAcl sacl, GenericAcl dacl)
答案 0 :(得分:2)
我最终使用了我在此处找到的一些代码,http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User
为了让一切都完成,我不得不跳过一些箍,但它有效。为了避免我遇到的错误,除了在整个用户之间切换之外,我还必须使用我发现的Impersonate内容。
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
// ...
//Copy the file. This allows our service account to take ownership of the copied file
var tempFileName = Path.Combine(Path.GetDirectoryName(file.FileName), "TEMP_" + file.FileNameOnly);
File.Copy(file.FileName, tempFileName);
var windowID = WindowsIdentity.GetCurrent();
var currUserName = windowID.User.Translate(typeof(NTAccount)).Value;
var splitChar = new[] { '\\' };
//var name = currUserName.Split(splitChar)[1];
//var domain = currUserName.Split(splitChar)[0];
var ediFileOwner = new NTAccount("TricorBraun", _radleyEDIEndpointUserAccount);
//We have to give Access to the service account to delete the original file
var fileSecurity = File.GetAccessControl(file.FileName);
var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
fileSecurity.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(file.FileName, fileSecurity);
File.Delete(file.FileName);
//We rename our file to get our original file name back
File.Move(tempFileName, file.FileName);
//The following give our desired user permissions to take Ownership of the file.
//We have to do this while running under the service account.
fileSecurity = File.GetAccessControl(file.FileName);
var aosSID = (SecurityIdentifier) ediFileOwner.Translate(typeof(SecurityIdentifier));
fileSecurity.AddAccessRule(new FileSystemAccessRule(aosSID, FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(file.FileName, fileSecurity);
//Now we user the Impersonator (http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User)
//This allows us to manage the file as the Account we wish to change ownership to.
//It makes itself the owner.
using (new Impersonator(_radleyEDIEndpointUserAccount, "MyDomain", "password")) {
_logger.Debug(string.Format("Attempting changing owner to Tricorbraun\\{0}", _radleyEDIEndpointUserAccount));
fileSecurity = File.GetAccessControl(file.FileName);
fileSecurity.SetOwner(ediFileOwner); //Change our owner from LocalAdmin to our chosen DAX User
_logger.Debug(string.Format("Setting owner to Tricorbraun - {0}", _radleyEDIEndpointUserAccount));
File.SetAccessControl(file.FileName, fileSecurity);
}