前面也提到了,前段時間在作Online Judge系統,在正式上線前有幾個比較老的版本,其中第一個版本使用ACL來控制權限以確保安全(可是這個版本徹底創建在IIS上,因此這樣作是沒效果的),遇到了一些問題,至於問題是什麼之後有機會再說,那麼解決這些問題曾想到一個辦法,更改文件的全部者。c#
在搜索引擎裏搜索「C# 修改文件全部者」都會搜索到不少相似《c# 更改文件訪問權限 全部者(適用於win7如下版本) 》,可是就沒出現過《c# 更改文件訪問權限 全部者(適用於各個Windows版本) 》。爲何要特地強調適用於win7如下版本,是由於安全
FileInfo fi = new FileInfo(@"d:\囧.txt"); FileSecurity fs = fi.GetAccessControl(); NTAccount currentAccount = (NTAccount)fs.GetOwner(typeof(NTAccount)); Console.WriteLine("先前的全部者爲 " + currentAccount.Value); NTAccount admins = new NTAccount("administrators");//注意 這裏是administrators 而不是administrator 他表示管理員組而非一個單個的賬號 fs.SetOwner(admins); fi.SetAccessControl(fs); Console.WriteLine("當前的全部者爲 " + fi.GetAccessControl().GetOwner(typeof(NTAccount)).Value);
這樣作會在Windows 7以及更高版本上go die(不容許將安全標識符做爲此對象的全部者),高版本Windows須要用Win32API,若是手工去操做會複雜不少。偶然在StackOverflow上找到一篇文章說到了一個解決方案,因爲年代久遠不可考(實際上是懶當時沒記忘了)因此就不貼原文了。dom
爆棧網上的答主給的方法是使用一個外部庫,這個庫看名字就知道是幹什麼的,用起來也特別方便:搜索引擎
貼段老代碼(應該是這麼用的,這個版本還能跑起來):code
File.Copy(outfileName, tempfileName); var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null); var domain = new FileInfo(outfileName).GetAccessControl().GetOwner(typeof(NTAccount)).Value.Split('\\')[0]; var user = new FileInfo(outfileName).GetAccessControl().GetOwner(typeof(NTAccount)).Value.Split('\\')[1]; var ediFileOwner = new NTAccount(domain, user); var fileSecurity = File.GetAccessControl(outfileName); File.SetAccessControl(outfileName, fileSecurity); File.Delete(outfileName); File.Move(tempfileName, outfileName); var aosSID = (SecurityIdentifier)ediFileOwner.Translate(typeof(SecurityIdentifier)); File.SetAccessControl(outfileName, fileSecurity); using (new Impersonator(/*UserName*/, domain, /*UserPassword*/)) { fileSecurity = File.GetAccessControl(outfileName); fileSecurity.SetOwner(ediFileOwner); File.SetAccessControl(outfileName, fileSecurity); }
在註釋處填寫要更改成的全部者的帳戶名和密碼。雖然看起來很複雜的樣子,其實過程很是簡單:建立源文件的副本,得到它的信息,幹掉源文件,更名副本而後調用Impersonator來設置全部者。對象
使用前,這個鍋是楊某的:blog
執行後,這個鍋就甩了:索引