服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 文件安全管理需要注意的

C# 文件安全管理需要注意的

2022-11-08 12:13彭泽0902 C#

这篇文章主要介绍了C# 文件安全管理需要注意的,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下

       在实际的项目开发中,我们经常需要使用到文件的I/O操作,主要包含对文件的增改删查等操作,这些基本的操作我们都是很熟悉,但是较少的人去考虑文件的安全和操作的管理等方面,例如文件的访问权限管理,文件数据的彻底删除和数据的恢复等等,这一系列的操作需要我们对.NET的相关知识有一个深刻的学习。

       在本文章主要介绍文件和目录的一些基本操作,以及文件目录的权限和安全设置的相关内容。

一.DotNet文件目录常用操作:

       提到文件的I/O操作,这个对于每一个开发者来说都不是陌生的事,因为这些操作是我们在项目开发过程中经常使用到的一些操作。那么在.NET中操作文件的类在System.IO命名空间下,一下介绍一下常见的I/O操作类:

        DiveInfo:提供了对逻辑磁盘的基本信息访问的途径。(只能查看信息,不能做任何修改。)

        System.Environment:用来枚举驱动器。(不能获取驱动器的属性)

        System.Management:.NET针对WMI调用。

        Directory和DircetoryInfo:用于操作目录。(前者为静态类,后者则须在实例化后调用,功能上相同)

        File和FileInfo:用于操作文件。(前者为静态类,后者须实例化后调用,功能上相同)

    以上介绍了一些文件的基本操作类,本次主要讲解目录和文件操作,一下给出文件和目录操作的一些基本方法:

   1.文件常规操作:

      (1).文件读写操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/// <summary>
/// 写文件
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="content">文件内容</param>
/// <param name="encoding">指定文件编码</param>
protected void Write_Txt(string fileName, string content, string encoding)
{
 if (string.IsNullOrEmpty(fileName))
 {
  throw new ArgumentNullException(fileName);
 }
 if (string.IsNullOrEmpty(content))
 {
  throw new ArgumentNullException(content);
 }
 if (string.IsNullOrEmpty(encoding))
 {
  throw new ArgumentNullException(encoding);
 }
 var code = Encoding.GetEncoding(encoding);
 var htmlfilename = HttpContext.Current.Server.MapPath("Precious\\" + fileName + ".txt");
 var str = content;
 var sw = StreamWriter.Null;
 try
 {
  using (sw = new StreamWriter(htmlfilename, false, code))
  {
   sw.Write(str);
   sw.Flush();
  }
 }
 catch (IOException ioex)
 {
  throw new IOException(ioex.Message);
 }
 catch (Exception ex)
 {
  throw new Exception(ex.Message);
 }
 finally
 {
  sw.Close();
 }
}
 
/// <summary>
/// 读文件
/// </summary>
/// <param name="filename">文件路径</param>
/// <param name="encoding">文件编码</param>
/// <returns></returns>
protected string Read_Txt(string filename, string encoding)
{
 if (string.IsNullOrEmpty(filename))
 {
  throw new ArgumentNullException(filename);
 }
 if (string.IsNullOrEmpty(encoding))
 {
  throw new ArgumentNullException(encoding);
 }
 var code = Encoding.GetEncoding(encoding);
 var temp = HttpContext.Current.Server.MapPath("Precious\\" + filename + ".txt");
 var str = string.Empty;
 if (!System.IO.File.Exists(temp)) return str;
 var sr = StreamReader.Null;
 try
 {
  using (sr = new StreamReader(temp, code))
  {
   str = sr.ReadToEnd();
  }
 }
 catch (IOException ioex)
 {
  throw new IOException(ioex.Message);
 }
 catch (Exception ex)
 {
  throw new Exception(ex.Message);
 }
 finally
 {
  sr.Close();
 }
 return str;
}

    (2).文件附加操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/// <summary>
/// 拷贝文件
/// </summary>
/// <param name="orignFile">原始文件</param>
/// <param name="newFile">新文件路径</param>
public static void FileCoppy(string orignFile, string newFile)
{
 if (string.IsNullOrEmpty(orignFile))
 {
  throw new ArgumentException(orignFile);
 }
 if (string.IsNullOrEmpty(newFile))
 {
  throw new ArgumentException(newFile);
 }
 System.IO.File.Copy(orignFile, newFile, true);
}
 
/// <summary>
/// 删除文件
/// </summary>
/// <param name="path">路径</param>
public static void FileDel(string path)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentException(path);
 }
 System.IO.File.Delete(path);
}
 
/// <summary>
/// 移动文件
/// </summary>
/// <param name="orignFile">原始路径</param>
/// <param name="newFile">新路径</param>
public static void FileMove(string orignFile, string newFile)
{
 if (string.IsNullOrEmpty(orignFile))
 {
  throw new ArgumentException(orignFile);
 }
 if (string.IsNullOrEmpty(newFile))
 {
  throw new ArgumentException(newFile);
 }
 System.IO.File.Move(orignFile, newFile);
}

    2.目录常规操作:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/// <summary>
/// 在当前目录下创建目录
/// </summary>
/// <param name="orignFolder">当前目录</param>
/// <param name="newFloder">新目录</param>
public static void FolderCreate(string orignFolder, string newFloder)
{
 if (string.IsNullOrEmpty(orignFolder))
 {
  throw new ArgumentException(orignFolder);
 }
 if (string.IsNullOrEmpty(newFloder))
 {
  throw new ArgumentException(newFloder);
 }
 Directory.SetCurrentDirectory(orignFolder);
 Directory.CreateDirectory(newFloder);
}
 
/// <summary>
/// 创建文件夹
/// </summary>
/// <param name="path"></param>
public static void FolderCreate(string path)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentException(path);
 }
 if (!Directory.Exists(path))
 {
  Directory.CreateDirectory(path);
 }   
}
 
public static void FileCreate(string path)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentException(path);
 }
 var createFile = new FileInfo(path);
 if (createFile.Exists) return;
 var fs = createFile.Create();
 fs.Close();
 fs.Dispose();
}
 
/// <summary>
/// 递归删除文件夹目录及文件
/// </summary>
/// <param name="dir"></param>
/// <returns></returns>
public static void DeleteFolder(string dir)
{
 if (string.IsNullOrEmpty(dir))
 {
  throw new ArgumentException(dir);
 }
 if (!Directory.Exists(dir)) return;
 foreach (var d in Directory.GetFileSystemEntries(dir))
 {
  if (System.IO.File.Exists(d))
  {
   //直接删除其中的文件
   System.IO.File.Delete(d);
  }
  else
  {
   //递归删除子文件夹
   DeleteFolder(d);
  }    
 }
 //删除已空文件夹 
 Directory.Delete(dir, true);  
}
 
/// <summary>
/// 指定文件夹下面的所有内容copy到目标文件夹下面
/// </summary>
/// <param name="srcPath">原始路径</param>
/// <param name="aimPath">目标文件夹</param>
public static void CopyDir(string srcPath, string aimPath)
{
 if (string.IsNullOrEmpty(srcPath))
 {
  throw new ArgumentNullException(srcPath);
 }
 if (string.IsNullOrEmpty(aimPath))
 {
  throw new ArgumentNullException(aimPath);
 }
 try
 {
  if (aimPath[aimPath.Length - 1] != Path.DirectorySeparatorChar)
  {
   aimPath += Path.DirectorySeparatorChar;
  }
  if (!Directory.Exists(aimPath))
  {
   Directory.CreateDirectory(aimPath);
  }
  var fileList = Directory.GetFileSystemEntries(srcPath);
  foreach (var file in fileList)
  {
   if (Directory.Exists(file))
   {
    CopyDir(file, aimPath + Path.GetFileName(file));
   }
   else
   {
    System.IO.File.Copy(file, aimPath + Path.GetFileName(file), true);
   }
  }
 }
 catch (IOException ioex)
 {
  throw new IOException(ioex.Message);
 }
 catch (Exception ee)
 {
  throw new Exception(ee.ToString());
 }
}
 
/// <summary>
/// 获取指定文件夹下所有子目录及文件
/// </summary>
/// <param name="path">详细路径</param>
public static string GetFoldAll(string path)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentNullException(path);
 }
 var str =string.Empty;
 var thisOne = new DirectoryInfo(path);
 str = ListTreeShow(thisOne, 0, str);
 return str;
 
}
 
/// <summary>
/// 获取指定文件夹下所有子目录及文件函数
/// </summary>
/// <param name="theDir">指定目录</param>
/// <param name="nLevel">默认起始值,调用时,一般为0</param>
/// <param name="rn">用于迭加的传入值,一般为空</param>
/// <returns></returns>
public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn)
{
 if (theDir == null)
 {
  throw new ArgumentNullException("theDir");
 }
 //获得目录
 DirectoryInfo[] subDirectories = theDir.GetDirectories();
 foreach (DirectoryInfo dirinfo in subDirectories)
 {
 
  if (nLevel == 0)
  {
   rn += "├";
  }
  else
  {
   var s =string.Empty;
   for (int i = 1; i <= nLevel; i++)
   {
    s += "│&nbsp;";
   }
   rn += s + "├";
  }
  rn += "<b>" + dirinfo.Name + "</b><br />";
  //目录下的文件
  var fileInfo = dirinfo.GetFiles();
  foreach (FileInfo fInfo in fileInfo)
  {
   if (nLevel == 0)
   {
    rn += "│&nbsp;├";
   }
   else
   {
    var f = string.Empty;
    for (int i = 1; i <= nLevel; i++)
    {
     f += "│&nbsp;";
    }
    rn += f + "│&nbsp;├";
   }
   rn += fInfo.Name.ToString() + " <br />";
  }
  rn = ListTreeShow(dirinfo, nLevel + 1, rn);
 
 
 }
 return rn;
}
 
/// <summary>
/// 获取指定文件夹下所有子目录及文件(下拉框形)
/// </summary>
/// <param name="path">详细路径</param>
///<param name="dropName">下拉列表名称</param>
///<param name="tplPath">默认选择模板名称</param>
public static string GetFoldAll(string path, string dropName, string tplPath)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentNullException(path);
 }
 if (string.IsNullOrEmpty(tplPath))
 {
  throw new ArgumentNullException(tplPath);
 }
 var strDrop = "<select name=\"" + dropName + "\" id=\"" + dropName + "\"><option value=\"\">--请选择详细模板--</option>";
 var str =string.Empty;
 DirectoryInfo thisOne = new DirectoryInfo(path);
 str = ListTreeShow(thisOne, 0, str, tplPath);
 return strDrop + str + "</select>";
 
}
 
/// <summary>
/// 获取指定文件夹下所有子目录及文件函数
/// </summary>
/// <param name="theDir">指定目录</param>
/// <param name="nLevel">默认起始值,调用时,一般为0</param>
/// <param name="rn">用于迭加的传入值,一般为空</param>
/// <param name="tplPath">默认选择模板名称</param>
/// <returns></returns>
public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn, string tplPath)
{
 if (theDir == null)
 {
  throw new ArgumentNullException("theDir");
 }
 //获得目录
 DirectoryInfo[] subDirectories = theDir.GetDirectories();
 foreach (DirectoryInfo dirinfo in subDirectories)
 {
  rn += "<option value=\"" + dirinfo.Name + "\"";
  if (string.Equals(tplPath, dirinfo.Name, StringComparison.CurrentCultureIgnoreCase))
  {
   rn += " selected ";
  }
  rn += ">";
 
  if (nLevel == 0)
  {
   rn += "┣";
  }
  else
  {
   string s = string.Empty;
   for (int i = 1; i <= nLevel; i++)
   {
    s += "│&nbsp;";
   }
   rn += s + "┣";
  }
  rn += "" + dirinfo.Name + "</option>";
  //目录下的文件
  FileInfo[] fileInfo = dirinfo.GetFiles();
  foreach (FileInfo fInfo in fileInfo)
  {
   rn += "<option value=\"" + dirinfo.Name + "/" + fInfo.Name + "\"";
   if (string.Equals(tplPath, fInfo.Name, StringComparison.CurrentCultureIgnoreCase))
   {
    rn += " selected ";
   }
   rn += ">";
 
   if (nLevel == 0)
   {
    rn += "│&nbsp;├";
   }
   else
   {
    string f = string.Empty;
    for (int i = 1; i <= nLevel; i++)
    {
     f += "│&nbsp;";
    }
    rn += f + "│&nbsp;├";
   }
   rn += fInfo.Name + "</option>";
  }
  rn = ListTreeShow(dirinfo, nLevel + 1, rn, tplPath);
 }
 return rn;
}
 
/// <summary>
/// 获取文件夹大小
/// </summary>
/// <param name="dirPath">文件夹路径</param>
/// <returns></returns>
public static long GetDirectoryLength(string dirPath)
{
 if (string.IsNullOrEmpty(dirPath))
 {
  throw new ArgumentNullException(dirPath);
 }
 if (!Directory.Exists(dirPath))
 {
  return 0;
 }   
 long len = 0;
 DirectoryInfo di = new DirectoryInfo(dirPath);
 foreach (FileInfo fi in di.GetFiles())
 {
  len += fi.Length;
 }
 DirectoryInfo[] dis = di.GetDirectories();
 if (dis.Length > 0)
 {
  for (int i = 0; i < dis.Length; i++)
  {
   len += GetDirectoryLength(dis[i].FullName);
  }
 }
 return len;
}
 
/// <summary>
/// 获取指定文件详细属性
/// </summary>
/// <param name="filePath">文件详细路径</param>
/// <returns></returns>
public static string GetFileAttibe(string filePath)
{
 if (string.IsNullOrEmpty(filePath))
 {
  throw new ArgumentNullException(filePath);
 }
 var str = string.Empty;
 FileInfo objFi = new FileInfo(filePath);
 str += "详细路径:" + objFi.FullName + "<br>文件名称:" + objFi.Name + "<br>文件长度:" + objFi.Length + "字节<br>创建时间" + objFi.CreationTime.ToString() + "<br>最后访问时间:" + objFi.LastAccessTime.ToString() + "<br>修改时间:" + objFi.LastWriteTime.ToString() + "<br>所在目录:" + objFi.DirectoryName + "<br>扩展名:" + objFi.Extension;
 return str;
}

二.DotNet文件目录访问管理:

    1.文件目录权限概述:

       提到权限这个概念,这对于每一个开发者都是再熟悉不过的,因为我们在开发项目时,都会考虑用户权限管理等等,但是文件的权限操作呢?这里我们就简单的介绍一下.NET中对文件访问权限的访问和设置。文件权限中的访问控制列表: 自由访问控制列表(DACL):Microsoft Windows NT和更高版本用于保护资源的机制;系统访问控制列表(SACL):一种控制与资源关联的审核消息的机制。System.Security.AccessControl命名空间通过一些类提供对访问控制列表的访问。DiectorySecurity:该类指定目录的访问控制和审核安全。指定系统目录的访问权限以及访问尝试的审核方式。FileSecurity:该类指定系统文件的访问权限以及如何审核访问尝试。

     下面介绍一下文件权限操作的类和方法:

      (1).FileStream类GetAccessControl():检索文件的安全对象:

?
1
2
3
4
5
6
7
8
9
[SecuritySafeCritical]
public FileSecurity GetAccessControl()
{
 if (this._handle.IsClosed)
 {
  __Error.FileNotOpen();
 }
 return new FileSecurity(this._handle, this._fileName, AccessControlSections.Group | AccessControlSections.Owner | AccessControlSections.Access);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
[SecurityCritical, SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
internal FileSecurity(SafeFileHandle handle, string fullPath, AccessControlSections includeSections) : base(false, handle, includeSections, false)
{
 if (fullPath != null)
 {
  new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();
 }
 else
 {
  new FileIOPermission(PermissionState.Unrestricted).Demand();
 }
}

    (2).FileStream类SetAccessControl():保存设置。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
[SecuritySafeCritical]
public void SetAccessControl(FileSecurity fileSecurity)
{
 if (fileSecurity == null)
 {
  throw new ArgumentNullException("fileSecurity");
 }
 if (this._handle.IsClosed)
 {
  __Error.FileNotOpen();
 }
 fileSecurity.Persist(this._handle, this._fileName);
}

  2.文件共享操作实例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/// <summary>
/// 共享文档操作
/// </summary>
public class FileSharingOperationHelper
{
 public static bool ConnectState(string path)
 {
  if (string.IsNullOrEmpty(path))
  {
   throw new ArgumentNullException(path);
  }
  return ConnectState(path, "", "");
 }
 
 /// <summary>
 /// 连接远程共享文件夹
 /// </summary>
 /// <param name="path">远程共享文件夹的路径</param>
 /// <param name="userName">用户名</param>
 /// <param name="passWord">密码</param>
 /// <returns></returns>
 public static bool ConnectState(string path, string userName, string passWord)
 {
  var proc = new Process();
  try
  {
   proc.StartInfo.FileName = "cmd.exe";
   proc.StartInfo.UseShellExecute = false;
   proc.StartInfo.RedirectStandardInput = true;
   proc.StartInfo.RedirectStandardOutput = true;
   proc.StartInfo.RedirectStandardError = true;
   proc.StartInfo.CreateNoWindow = true;
   proc.Start();
   var dosLine = "net use " + path + " " + passWord + " /user:" + userName;
   proc.StandardInput.WriteLine(dosLine);
   proc.StandardInput.WriteLine("exit");
   while (!proc.HasExited)
   {
    proc.WaitForExit(1000);
   }
   var errormsg = proc.StandardError.ReadToEnd();
   proc.StandardError.Close();
   if (!string.IsNullOrEmpty(errormsg))
   {
    throw new Exception(errormsg);
   }
  }
  catch (Exception ex)
  {
   throw new Exception(ex.Message);
  }
  finally
  {
   proc.Close();
   proc.Dispose();
  }
  return true;
 }
 
 /// <summary>
 /// 向远程文件夹保存本地内容,或者从远程文件夹下载文件到本地
 /// </summary>
 /// <param name="src">要保存的文件的路径,如果保存文件到共享文件夹,这个路径就是本地文件路径如:@"D:\1.avi"</param>
 /// <param name="dst">保存文件的路径,不含名称及扩展名</param>
 /// <param name="fileName">保存文件的名称以及扩展名</param>
 public static void Transport(string src, string dst, string fileName)
 {
  if (string.IsNullOrEmpty(src))
  {
   throw new ArgumentNullException(src);
  }
  if (string.IsNullOrEmpty(dst))
  {
   throw new ArgumentNullException(dst);
  }
  if (string.IsNullOrEmpty(fileName))
  {
   throw new ArgumentNullException(fileName);
  }
  FileStream inFileStream = null;
  FileStream outFileStream = null;
  try
  {
   inFileStream = new FileStream(src, FileMode.Open);
   if (!Directory.Exists(dst))
   {
    Directory.CreateDirectory(dst);
   }
   dst = dst + fileName;
   outFileStream = new FileStream(dst, FileMode.OpenOrCreate);
   var buf = new byte[inFileStream.Length];
   int byteCount;
   while ((byteCount = inFileStream.Read(buf, 0, buf.Length)) > 0)
   {
    outFileStream.Write(buf, 0, byteCount);
   }
  }
  catch (IOException ioex)
  {
   throw new IOException(ioex.Message);
  }
  catch (Exception ex)
  {
   throw new Exception(ex.Message);
  }
  finally
  {
   if (inFileStream != null)
   {
    inFileStream.Flush();
    inFileStream.Close();
   }
   if (outFileStream != null)
   {
    outFileStream.Flush();
    outFileStream.Close();
   }
  }
 }
}

    文件权限的规则:容器的访问规则可能被配置为不仅应用于对象本身,而且还应用于它的子对象、子容器或这两者。每个访问规则不是显示的就是继承的。DACL可以有对象的所有者任意修改,还可以由所有者已经给予其梗概DACL权限的任何更改。对象的安全描述包含另一个规则列表,称为系统访问权限列表(SACL),该列表将控制系统对对象执行哪个类型的审核。审核是一种具有安全敏感性的操作。在windows中,审核只能由本地安全机构(LSA)生成,LSA是唯一允许向安全事件日志中写入的组件。

三.DotNet彻底删除文件操作:

    1.文件彻底删除概述:

       看到文件删除,可能有人会问,前面不是已经介绍过文件的删除操作吗?为什么这里还需要详细的介绍。不错,上面的确介绍了文件和目录的删除方法,但是这里是介绍如何彻底的删除文件。我们常规的删除文件和文件格式化,一般是可以被恢复的。我们在操作删除的时候,只是将文件的索引给删除了,并没有删除实际的内容。文件的索引记录了文件在磁盘中的位置信息,当执行删除操作时,只是从文件分配聊表中删除了目录。

       那么可能会有人问,怎么讲文件彻底的删除呢?文件的粉碎,其实就是在删除文件分配列表的同时,把文件在磁盘上占用的所有扇区数据置为0。

       在.NET中提供了两种文件彻底的方法:

          (1).调用系统API来完成这样的“粉碎”操作。

          (2).在删除文件之前先删除文件的所有内容,然后在执行删除操作,被称为“假粉碎”。(此方法可以被人恢复文件,但是恢复的数据只是文件中的0)

      为了文件安全,可以采用多轮粉碎的方式:第一轮,通过文件操作Windows API,找到原始文件的铭文在存储器上所载区域,逐字符逐位进行完全填充,全部填充为0。第二轮,通过磁盘操作WindowsAPI找到原始文件或目录在FAT表中的位置,将原始文件或目录在FAT表中项清零。第三轮,通过磁盘操作WindowsAPI,找到原始文件或目录在备份FAT表的位置,将原始文件或目录在备份FAT表中的表项清零。

    2.文件彻底删除实例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/// <summary>
/// 粉碎文件操作
/// </summary>
public class KillFileHelper
{
 /// <summary>
 /// 强力粉碎文件,文件如果被打开,很难粉碎
 /// </summary>
 /// <param name="filename">文件全路径</param>
 /// <param name="deleteCount">删除次数</param>
 /// <param name="randomData">随机数据填充文件,默认true</param>
 /// <param name="blanks">空白填充文件,默认false</param>
 /// <returns>true:粉碎成功,false:粉碎失败</returns>
 public static bool KillFile(string filename, int deleteCount, bool randomData = true, bool blanks = false)
 {
  if (string.IsNullOrEmpty(filename))
  {
   throw new ArgumentNullException(filename);
  }
  const int bufferLength = 1024000;
  var ret = true;
  try
  {
   using (var stream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
   {
    var f = new FileInfo(filename);
    var count = f.Length;
    long offset = 0;
    var rowDataBuffer = new byte[bufferLength];
    while (count >= 0)
    {
     var iNumOfDataRead = stream.Read(rowDataBuffer, 0, bufferLength);
     if (iNumOfDataRead == 0)
     {
      break;
     }
     if (randomData)
     {
      var randombyte = new Random();
      randombyte.NextBytes(rowDataBuffer);
     }
     else if (blanks)
     {
      for (var i = 0; i < iNumOfDataRead; i++)
       rowDataBuffer[i] = 0;
     }
     else
     {
      for (var i = 0; i < iNumOfDataRead; i++)
       rowDataBuffer[i] = Convert.ToByte(Convert.ToChar(deleteCount));
     }
     // 写新内容到文件。
     for (var i = 0; i < deleteCount; i++)
     {
      stream.Seek(offset, SeekOrigin.Begin);
      stream.Write(rowDataBuffer, 0, iNumOfDataRead);
     }
     offset += iNumOfDataRead;
     count -= iNumOfDataRead;
    }
   }
   //每一个文件名字符代替随机数从0到9。
   var newName = "";
   do
   {
    var random = new Random();
    var cleanName = Path.GetFileName(filename);
    var dirName = Path.GetDirectoryName(filename);
    var iMoreRandomLetters = random.Next(9);
    // 为了更安全,不要只使用原文件名的大小,添加一些随机字母。
    for (var i = 0; i < cleanName.Length + iMoreRandomLetters; i++)
    {
     newName += random.Next(9).ToString();
    }
    newName = dirName + "\\" + newName;
   } while (File.Exists(newName));
   // 重命名文件的新的随机的名字。
   File.Move(filename, newName);
   File.Delete(newName);
  }
  catch
  {
   //可能其他原因删除失败了,使用我们自己的方法强制删除
   var matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
   try
   {
    //要检查被那个进程占用的文件
    var fileName = filename;
    var tool = new Process { StartInfo = { FileName = "handle.exe", Arguments = fileName + " /accepteula", UseShellExecute = false, RedirectStandardOutput = true } };
    tool.Start();
    tool.WaitForExit();
    var outputTool = tool.StandardOutput.ReadToEnd();
    foreach (Match match in Regex.Matches(outputTool, matchPattern))
    {
     //结束掉所有正在使用这个文件的程序
     Process.GetProcessById(int.Parse(match.Value)).Kill();
    }
    File.Delete(fileName);
   }
   catch
   {
    ret = false;
   }
  }
  return ret;
 }
}

四.DotNet文件加密解密操作:

   上面介绍了文件的基本操作,文件权限操作,文件的删除操作,最后介绍一下文件的加密和解密操作。File和FileInfo类对文件加密进行了进一步的封装,提供了Encrypt和Decrypt方法用来对文件加密和解密。这两种方法要求文件系统必须为NFTS系统,对操作系统版本也要求必须是NT以上版本,使用该方法加密的文件,必须由同一用户才能进行解密。

   具体看一下该方法的实现代码:

   1.Encrypt():文件加密操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[SecuritySafeCritical]
public static void Encrypt(string path)
{
 if (path == null)
 {
  throw new ArgumentNullException("path");
 }
 string fullPathInternal = Path.GetFullPathInternal(path);
 new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();
 if (!Win32Native.EncryptFile(fullPathInternal))
 {
  int errorCode = Marshal.GetLastWin32Error();
  if (errorCode == 5)
  {
   DriveInfo info = new DriveInfo(Path.GetPathRoot(fullPathInternal));
   if (!string.Equals("NTFS", info.DriveFormat))
   {
    throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));
   }
  }
  __Error.WinIOError(errorCode, fullPathInternal);
 }
}

   2.Decrypt():文件解密操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[SecuritySafeCritical]
public static void Decrypt(string path)
{
 if (path == null)
 {
  throw new ArgumentNullException("path");
 }
 string fullPathInternal = Path.GetFullPathInternal(path);
 new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();
 if (!Win32Native.DecryptFile(fullPathInternal, 0))
 {
  int errorCode = Marshal.GetLastWin32Error();
  if (errorCode == 5)
  {
   DriveInfo info = new DriveInfo(Path.GetPathRoot(fullPathInternal));
   if (!string.Equals("NTFS", info.DriveFormat))
   {
    throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));
   }
  }
  __Error.WinIOError(errorCode, fullPathInternal);
 }
}

五.总结:

       以上简单的介绍了文件的操作和文件的权限管理方法,如果需要更加深入的了解这些操作方法,可以查看msdn,或者查看.NET的“垫片”,查看相应的接口。在当代社会中,数据安全和文件安全都是很重要的,我们应该更加深入的去学习安全知识,提高系统的稳定性。

以上就是C# 文件安全管理需要注意的的详细内容,更多关于C# 文件安全管理的资料请关注服务器之家其它相关文章!

原文链接:https://cloud.tencent.com/developer/article/1013351

延伸 · 阅读

精彩推荐
  • C#C# char[]与string byte[]与string之间的转换详解

    C# char[]与string byte[]与string之间的转换详解

    在本篇文章里小编给大家分享的是关于C# char[]与string byte[]与string之间的转换的知识点内容,需要的朋友们参考下...

    驼鹿行动6832022-08-09
  • C#WPF中的ListBox实现按块显示元素的方法

    WPF中的ListBox实现按块显示元素的方法

    这篇文章主要介绍了WPF中的ListBox实现按块显示元素的方法,涉及ListBox属性设置相关操作技巧,需要的朋友可以参考下...

    永远爱好写程序8842021-12-07
  • C#C# 中对象序列化XML的方法

    C# 中对象序列化XML的方法

    这篇文章主要介绍了C# 中对象序列化XML的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...

    王月半子7262022-11-04
  • C#理解C#编程中的静态类和静态成员以及密封类

    理解C#编程中的静态类和静态成员以及密封类

    这篇文章主要介绍了理解C#编程中的静态类和静态成员以及密封类,注意类成员的相关访问限制和类的继承问题,需要的朋友可以参考下...

    C#教程网5152021-11-09
  • C#JWT.net 操作实践方法

    JWT.net 操作实践方法

    下面小编就为大家分享一篇JWT.net 操作实践方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    星辉Johnson7482022-02-16
  • C#Unity UGUI教程之实现滑页效果

    Unity UGUI教程之实现滑页效果

    使用UGUI提供的ScrollRect和ScrollBar组件实现基本滑动以及自己控制每次移动一页来达到滑页的效果。具体实现思路请参考下本教程...

    玄雨8002021-11-17
  • C#一文带你了解 C# DLR 的世界(DLR 探秘)

    一文带你了解 C# DLR 的世界(DLR 探秘)

    DLR 是 C#4.0 新引进来的概念,其主要目的就是为了动态绑定与交互。下面小编给大家带来一篇不错教程,一文带你了解 C# DLR 的世界,需要的朋友可以参考下...

    沉睡的木木夕4982022-08-28
  • C#webBrowser执行js的方法,并返回值,c#后台取值的实现

    webBrowser执行js的方法,并返回值,c#后台取值的实现

    下面小编就为大家带来一篇webBrowser执行js的方法,并返回值,c#后台取值的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过...

    C#教程网11172021-12-13