有一个讨厌的问题,我基本上不知道它来自哪里:( 所以,主题是: 当尝试从localhost(来自实际文件系统)检查文件夹权限时,它(下面附带的代码)工作正常,但是当从网络启动应用程序时(例如:\ * machinename *)则不然。 当我请求任何权限时,我总是通过网络获得批准,但是无法创建文件,例如,因为我没有足够的权限 许可!
iccFile_Security =
class
const
FILE_READ_DATA = $0001;
FILE_WRITE_DATA = $0002;
FILE_APPEND_DATA = $0004;
FILE_READ_EA = $0008;
FILE_WRITE_EA = $0010;
FILE_EXECUTE = $0020;
FILE_READ_ATTRIBUTES = $0080;
FILE_WRITE_ATTRIBUTES = $0100;
FILE_GENERIC_READ = ( STANDARD_RIGHTS_READ
or FILE_READ_DATA
or FILE_READ_ATTRIBUTES
or FILE_READ_EA
or SYNCHRONIZE
);
FILE_GENERIC_WRITE = ( STANDARD_RIGHTS_WRITE
or FILE_WRITE_DATA
or FILE_WRITE_ATTRIBUTES
or FILE_WRITE_EA
or FILE_APPEND_DATA
or SYNCHRONIZE
);
FILE_GENERIC_EXECUTE = ( STANDARD_RIGHTS_EXECUTE
or FILE_READ_ATTRIBUTES
or FILE_EXECUTE
or SYNCHRONIZE
);
FILE_ALL_ACCESS = ( STANDARD_RIGHTS_REQUIRED
or SYNCHRONIZE
or $1FF
);
strict private
public
class function check( _filename : String; _desiredAccess : DWORD ) : Boolean; overload;
class function check( _filename : String; _desiredAccess : DWORD; out _failed : Boolean) : Boolean; overload;
end;
implementation
{ iccFile_Security }
class function iccFile_Security.check( _filename: String; _desiredAccess: DWORD) : Boolean;
var _failed : Boolean;
begin
result := check( _filename, _desiredAccess, _failed) and not _failed;
end;
class function iccFile_Security.check( _filename : String; _desiredAccess : DWORD; out _failed : Boolean) : Boolean;
var Token : DWORD;
Status : LongBool;
Access : DWORD;
SecDescSize : DWORD;
PrivSetSize : DWORD;
PrivSet : PRIVILEGE_SET;
Mapping : GENERIC_MAPPING;
SecDesc : PSECURITY_DESCRIPTOR;
begin
Result := False;
SecDesc := nil;
SecDescSize := 0;
try
GetFileSecurity( pchar( _filename),
OWNER_SECURITY_INFORMATION
or GROUP_SECURITY_INFORMATION
or DACL_SECURITY_INFORMATION,
nil,
0,
SecDescSize
);
SecDesc := GetMemory( SecDescSize);
if not GetFileSecurity( pchar( _filename),
OWNER_SECURITY_INFORMATION
or GROUP_SECURITY_INFORMATION
or DACL_SECURITY_INFORMATION,
SecDesc,
SecDescSize,
SecDescSize
)
then begin
_failed := true;
exit;
end;
ImpersonateSelf( SecurityImpersonation);
OpenThreadToken( GetCurrentThread, TOKEN_QUERY, False, Token);
if Token = 0
then begin
_failed := true;
exit;
end;
Mapping.GenericRead := FILE_GENERIC_READ;
Mapping.GenericWrite := FILE_GENERIC_WRITE;
Mapping.GenericExecute := FILE_GENERIC_EXECUTE;
Mapping.GenericAll := FILE_ALL_ACCESS;
MapGenericMask( Access, Mapping);
PrivSetSize := SizeOf( PrivSet);
AccessCheck( SecDesc, Token, _desiredAccess, Mapping, PrivSet, PrivSetSize, Access, Status);
CloseHandle( Token);
if _desiredAccess = Access
then result := Status;
finally
FreeMem( SecDesc, SecDescSize);
end;
end;
正确地工作:
if not iccFile_Security.check( 'C:\temp\', iccFile_Security.FILE_ALL_ACCESS)
then ...
不工作:
if not iccFile_Security.check( '\\testmachine\temp\', iccFile_Security.FILE_ALL_ACCESS)
then ...
有任何意见或建议吗? 任何帮助表示赞赏。
答案 0 :(得分:4)
阿。我以前回答过这个问题 - 网络文件安全性是一个不可靠的垃圾邮件。 (我倾倒了所有代码,只是为了检查我是否可以在目录中写一个文件。)
C.f。,http://www.ureader.com/msg/16591730.aspx
阅读有关AccessCheck()的讨论;具体是:
即使执行AccessCheck(),您也在进行访问检查 针对“本地”生成的访问令牌,使用 与对象关联的安全描述符。当你直接 访问远程系统上的对象,获取网络访问令牌 在远程系统上生成。此网络访问令牌用于 对对象执行访问检查以确定是否应该访问 被批准或被拒绝。该对象可以是文件或命名管道 或AD对象。
e.g。如果用户是远程管理员组的成员 系统,当你直接访问远程系统上的对象时, 在远程系统上生成的网络访问令牌将 拥有Administrators组并允许访问。然而,当你 使用本地访问令牌调用AccessCheck(),您将获得不同 结果