0

有一个烦人的问题,我基本上不知道它来自哪里:( 所以,主题是:当尝试从 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 ...

任何意见\建议?任何帮助表示赞赏。

4

1 回答 1

4

啊。我之前已经回答过这个问题——网络文件安全是一个不可靠的废话。(我为此倾倒了所有代码,而只是检查是否可以在目录中写入文件。)

参见,http: //www.ureader.com/msg/16591730.aspx

阅读有关 AccessCheck() 的讨论;具体来说:

即使在执行 AccessCheck() 时,您也正在对“本地”生成的访问令牌进行访问检查,并使用与对象关联的安全描述符。当您直接访问远程系统上的对象时,会在远程系统上生成网络访问令牌。此网络访问令牌用于对对象执行访问检查以确定是否应授予或拒绝访问。该对象可以是文件或命名管道或 AD 对象。

例如,如果用户是远程系统上管理员组的成员,当您直接访问远程系统上的对象时,在远程系统上生成的网络访问令牌将具有管理员组并允许访问。然而,当您使用本地访问令牌调用 AccessCheck() 时,您会得到不同的结果。

于 2012-06-22T15:47:38.450 回答