65.9K
CodeProject 正在变化。 阅读更多。
Home

检查用户对文件或文件夹的权限

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (9投票s)

2002 年 2 月 25 日

4分钟阅读

viewsIcon

212166

downloadIcon

3212

一个组件,用于检查给定用户对文件/文件夹是否具有特定的访问权限。

引言

我们经常面临关于 Web 应用程序的一个问题,那就是“用户对某个文件或文件夹拥有何种权限?”。这个问题的答案有助于确定用户可以在该对象上执行哪些操作,以及不能执行哪些操作。例如,在您的网站上,您希望某些用户能够读取文件的内容,但不允许他们对其进行任何修改。因此,如果您事先知道登录用户没有文件的写入权限,您可以隐藏或不向他们显示那些会引导他们执行该操作的按钮或控件。没有什么比一个沮丧的用户看到“您不允许执行此操作”的错误消息更糟糕的了。最好不要向用户显示他们无法执行的功能。

本文旨在实现一个组件,该组件可以检查特定的域用户是否对文件或文件夹具有特定权限。可以通过 ADSI 接口执行一些操作。在域控制器或服务器网络上使用 ADSI 是可以的。但是,当您只处理单台服务器时,所有调用都会通过 Net API 调用进行路由。我们尝试使用低级 Net API 调用来实现这个组件。没有使用 ADSI 接口。

安全背景

每当在 Windows 环境中创建对象(文件夹、文件、句柄、互斥体等)时,它都会与一个自由访问控制列表 (DACL) 相关联。DACL 包含一个访问控制条目 (ACE) 列表。每个 ACE 指定谁可以访问此对象,以及特定用户或组对该对象拥有何种类型的访问权限。

因此,这个实现背后的思想是获取对象的 DACL,然后检查 DACL 中是否存在特定用户的访问权限。

实现

该组件被开发为一个 ATL/COM ASP 组件。由于我们提到了 ATL,因此实现是使用 C++ 完成的。由于它被实现为一个 ASP 组件,因此该组件实现了IDispatch接口,以便像javascriptvbscriptVB等延迟绑定客户端可以使用它。

以下步骤描述了用于完成检查用户对对象权限任务的算法。

  1. 给定用户的登录 ID,获取相应的 SID。利用LookupAccountName API 来完成此步骤。
  2. bRetVal = ::LookupAccountName((strDCServer.length() == 0) ? NULL : strDCServer.c_str(),
    				strUser.c_str(),
    				pUserSID,
    				&cbUserSID,
    				pszDomain,
    				&cbDomain,
    				&snuType);
    

    在此项目中,此步骤已在GetUserSID函数中实现。请查看源代码以获取更多实现细节。

  3. 接下来,您需要获取与该对象关联的 SD 和 DACL。Platform SDK 提供了以下 API 来获取 SD。

    GetSecurityInfo
    GetNamedSecurityInfo

    我们使用了该 API 的早期版本。它返回与 SD 关联的 SD 和 DACL。请查看 SDK 文档以获取有关其用法和限制的更多信息。在项目中,此步骤已在GetFileSD函数中实现。
  4. dwErr = ::GetSecurityInfo(hFile,
    			  SE_FILE_OBJECT,
    			  secInfo,
    			  NULL,
    			  NULL,
    			  pACL,
    			  NULL,
    			  pFileSD);
    
  5. 下一步是检查指定访问权限是否存在于步骤 2 中获得的 DACL 中。我们使用了高级GetEffectiveRightsFromAcl安全 API 来获取描述用户对给定对象实际拥有权限的掩码。
  6. ACCESS_MASK mask;
    dwRetVal = ::GetEffectiveRightsFromAcl( pACL,
    					pTrustee,
    					&mask);
    

    此 API 的第二个参数是指向TRUSTEE结构的指针。此结构指定用户、组或登录会话信息。有四种不同的 API 风格可用于构建此结构。

    BuildTruteeWithSid
    BuildTrusteeWithName
    BuildTrusteeWithObjectsAndName
    BuildTrusteeWithObjectsAndSid
    我们使用了第一种风格来构建一个带有 SID 的TRUSTEE结构。

    BuildTrusteeWithSid(pTrustee, pUserSID);
    

    GetEffectiveRightsFromAcl函数返回一个DWORD值,指示访问掩码。此掩码可用于检查指定权限是否存在。此步骤已在类的GetUserRights函数中实现。

  7. 最后一步是检查步骤 3 中获得的掩码。
  8. lRetMask = this->GetUserRights(pUserSID, pFileDACL);
    if (lRetMask & lAccessToCheck)
    {
        *pbOK = TRUE;
    }
    else
    {
        *pbOK = FALSE;
    }
    

使用组件

如前所述,该组件已被实现为一个 ASP COM 组件。它包含ITrusteeUtil接口,该接口实现了几个接口。要检查访问权限,您需要调用CheckPermissionsOnFile方法。第三个参数是要检查权限的文件或文件夹的完整路径。第四个参数是要检查的访问掩码。此掩码可以使用与WinNT.h文件中指定的相同值来构建。其中一些值如下。

#define GENERIC_READ	(0x80000000L)
#define GENERIC_WRITE	(0x40000000L)
#define GENERIC_EXECUTE	(0x20000000L)
#define GENERIC_ALL	(0x10000000L)

我们在项目中包含了一个名为Masks.txt的文件,其中包含一些值。您可以查看它以将访问掩码指定给方法。

例如,要检查用户是否对文件夹具有写入权限,您可以如下使用它。

<%										
var hasWriteAccess;
obNet = Server.CreateObject('Pardesi.TrusteeUtil');

hasWriteAccess = obNet.CheckPermissionsOnFile("foo", "bar", "C:\\DataFiles", 0x0002)
Response.Write(hasWriteAccess);
Response.End();									
%>

路线图

该组件仍在开发中,并在各种环境下进行测试。请随意使用并查看实现,根据您的需求进行改进。对于建议和问题,请随时通过softomatix@pardesiservices.com与我们联系,或访问我们的Softomatix网站。

© . All rights reserved.