【问题标题】:Setting file owner throwing InvalidOperation exception设置文件所有者抛出 InvalidOperation 异常
【发布时间】:2012-12-10 13:02:49
【问题描述】:

我正在使用下面的代码来更改文件的所有者。此代码在用 C# 4.0 版编写的 Windows 服务中运行。它在本地服务器上运行,运行 Windows Server 2008 R2 Standard,Service Pack 1。

我需要将通过 FTP 接收的文件的所有者更改为域帐户。我可以登录该框并使用资源管理器手动执行此操作,但是当我尝试通过代码运行此操作时,我得到一个 InvalidOperation 异常。我可以将所有者更改为本地系统帐户,但不能更改为网络帐户。对此的任何帮助将不胜感激。

我正在使用一些奇怪的 Microsoft Dynamics AX 代码来处理 EDI 文件。该过程要求文件的所有者是有效的 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 安全信息、 SecurityIdentifier 所有者、SecurityIdentifier 组、GenericAcl sacl、 GenericAcl dacl)

【问题讨论】:

  • 需要更多信息。为什么不直接复制文件并删除原始文件。这将创建一个具有正确权限的新文件夹。否则,如果您希望使用您的代码,则需要有关已上传文件的更多信息。完整的例外也很有帮助。
  • 我已经添加了例外和我正在尝试做的事情的完整描述,或者至少我为什么要这样做。
  • 将您刚刚发布的评论放在您的问题中。

标签: c# security


【解决方案1】:

我最终使用了我在这里找到的一些代码,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);
}

【讨论】:

    猜你喜欢
    • 2023-01-24
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多