澳门在线威尼斯官方 > 澳门在线威尼斯官方 > 判断用户是否对路径拥有访问权限,Windows身份认

原标题:判断用户是否对路径拥有访问权限,Windows身份认

浏览次数:64 时间:2019-09-14

什么收获当前系统客商对文件/文件夹的操作权限?

细说ASP.NET Windows居民身份注明

读书目录

  • 开始
  • 认知ASP.NET Windows身份验证
  • 访问 Active Directory
  • 在ASP.NET中访问Active Directory
  • 运用Active Directory验证客户身份
  • 有惊无险上下文与顾客模拟
  • 在IIS中安排Windows身份验证
  • 关于浏览器的报到对话框难题
  • 在客商端代码中访谈Windows身份ID明的页面

上篇博客小编聊起了有个别有关ASP.NET Forms身份认证方面的话题,这一次的博客将首要介绍ASP.NET Windows身份验证。

Forms身份ID明即使选取大面积,不过,假使是在 Windows Active Directory 的条件中选取ASP.NET, 那么使用Windows身份认证也会相比较有利。 方便性表现为:我们毫不再规划登入页面,不用编写登入验证逻辑。何况选用Windows身份验证会有越来越好的普洱保证。

归来顶上部分

 1.获取安全消息DirectorySecurity

DirectorySecurity fileAcl = Directory.GetAccessControl(folder);

透过Directory.GetAccessControl获取文件夹的权柄/安全音讯

详细介绍,可参看MSDN官方文书档案)

对文本/文件夹权限的详尽操作,可参照一篇博客C#文本夹权限操作

认知ASP.NET Windows身份ID明

要选拔Windows身份认证形式,需求在web.config设置:

<authentication mode="Windows" />

Windows身份认证做为ASP.NET的暗中认可认证方法,与Forms身份ID明在广大基础方面是一样的。上篇博客我说过:自个儿感觉ASP.NET的身价评释的最主旨部分其实正是HttpContext.User那几个特性所指向的靶子。在接下去的局部,作者将注重深入分析这一个目的在三种居民身份评释中有怎么样差别。

在ASP.NET身份认证进度中,IPrincipal和IIdentity那三个接口有着非常重大的功用。 后面一个定义客商对象的基本效能,前面一个定义标记对象的基本成效, 差异的地位认证方法赢得的这几个接口的实例也是区别的。

ASP.NET Windows身份ID明是由WindowsAuthenticationModule完成的。WindowsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 使用从IIS传递到ASP.NET的Windows访谈令牌(Token)创立叁个WindowsIdentity对象,Token通过调用context.WorkerRequest.GetUserToken()获得, 然后再依照WindowsIdentity 对象创设WindowsPrincipal对象, 然后把它赋值给HttpContext.User。

在Forms身份认证中,我们需求创建登陆页面,让客商提交客商名和密码,然后检查顾客名和密码的正确, 接下来创立多个包蕴FormsAuthenticationTicket对象的登陆Cookie供后续诉求使用。FormsAuthenticationModule在ASP.NET管线的AuthenticateRequest事件中, 剖析登陆Cookie并创办几个满含FormsIdentity的GenericPrincipal对象, 然后把它赋值给HttpContext.User。

地点二段话归纳了回顾了三种身份认证方法的行事格局。 大家得以窥见它们存在以下差异: 1. Forms地位验证需求库克ie表示登陆状态,Windows身份认证则依赖于IIS 2. Windows居民身份表明没有须求大家统筹登陆页面,不用编写登入验证逻辑,由此更便于选择。

在授权阶段,UrlAuthorizationModule仍旧会基于当下客户检查将在访谈的能源是或不是获得许可。 接下来,FileAuthorizationModule检查 HttpContext.User.Identity 属性中的 IIdentity 对象是还是不是是 WindowsIdentity 类的一个实例。 假如 IIdentity 对象不是 WindowsIdentity 类的叁个实例,则 FileAuthorizationModule 类甘休管理。 假诺存在 WindowsIdentity 类的贰个实例,则 FileAuthorizationModule 类调用 AccessCheck Win32 函数(通过 P/Invoke) 来显著是否授权经过身份验证的客户端访谈恳求的公文。 如若该文件的安全描述符的妄动访谈调整列表 (DACL) 中至少含有二个 Read 访问调控项 (ACE),则允许该央求继续。 不然,FileAuthorizationModule 类调用 HttpApplication.CompleteRequest 方法并将情状码 401 重回到顾客端。

在Windows身份ID明中,验证职业尤为重假如由IIS实现的,WindowsAuthenticationModule其实只是承受创建WindowsPrincipal和WindowsIdentity而已。 顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5 身份验证”三种, 关于这三种Windows身份验证的越来越多表明可查阅MSDN技巧小说:表达:ASP.NET 2.0 中的 Windows 身份验证。 以作者之见,IIS最后利用哪一类Windows身份验证方法并不影响大家的付出进程,由此本文不会探讨这几个话题。

根据本身的实际上经验来看,使用Windows身份ID明时,主要的费用工作将是依靠登陆名从Active Directory获取顾客音讯。 因为,此时无需大家再规划登入进度,IIS与ASP.NET已经为大家图谋好了WindowsPrincipal和WindowsIdentity那二个与顾客地方相关的靶子。

归来最上端

2. 赢得文件夹访谈权限列表FileSystemAccessRule

var rules = fileAcl.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)).OfType<FileSystemAccessRule>().ToList();

GetAccessRules()方法再次来到的是AuthorizationRule集合,此处只须求得到文件权限。

FileSystemAccessRule.aspx)承继自AuthorizationRule,并新扩充俩个天性

  • AccessControlType -- 枚举 Allow/Deny
  • FileSystemRights -- 对文件的走访权限详细音信(读/写等),可知下边列表: 

图片 1图片 2

 1   /// <summary>定义要创建访问和审核规则时使用的访问权限。</summary>
 2   [Flags]
 3   public enum FileSystemRights
 4   {
 5     ReadData = 1,
 6     ListDirectory = ReadData, // 0x00000001
 7     WriteData = 2,
 8     CreateFiles = WriteData, // 0x00000002
 9     AppendData = 4,
10     CreateDirectories = AppendData, // 0x00000004
11     ReadExtendedAttributes = 8,
12     WriteExtendedAttributes = 16, // 0x00000010
13     ExecuteFile = 32, // 0x00000020
14     Traverse = ExecuteFile, // 0x00000020
15     DeleteSubdirectoriesAndFiles = 64, // 0x00000040
16     ReadAttributes = 128, // 0x00000080
17     WriteAttributes = 256, // 0x00000100
18     Delete = 65536, // 0x00010000
19     ReadPermissions = 131072, // 0x00020000
20     ChangePermissions = 262144, // 0x00040000
21     TakeOwnership = 524288, // 0x00080000
22     Synchronize = 1048576, // 0x00100000
23     FullControl = Synchronize | TakeOwnership | ChangePermissions | ReadPermissions | Delete | WriteAttributes | ReadAttributes | DeleteSubdirectoriesAndFiles | Traverse | WriteExtendedAttributes | ReadExtendedAttributes | CreateDirectories | CreateFiles | ListDirectory, // 0x001F01FF
24     Read = ReadPermissions | ReadAttributes | ReadExtendedAttributes | ListDirectory, // 0x00020089
25     ReadAndExecute = Read | Traverse, // 0x000200A9
26     Write = WriteAttributes | WriteExtendedAttributes | CreateDirectories | CreateFiles, // 0x00000116
27     Modify = Write | ReadAndExecute | Delete, // 0x000301BF
28   }

View Code

 因为AuthorizationRule中,IdentityReference对应权限的顾客/顾客组标记,格式为:"MYDOMAINMyAccount"

故此,如通过当前系统顾客名与IdentityReference相配,就能够获得FileSystemAccessRule权限。如何获得客户名,见下一段落

访问 Active Directory

作者们普通使用LDAP左券来访谈Active Directory, 在.net framework中提供了DirectoryEntry和DirectorySearcher那二个门类让大家能够一本万利地从托管代码中访谈Active Directory 域服务。

假如大家要在"test.corp”这几个域中寻觅有个别客商音信,我们能够利用下边包车型地铁语句构造二个DirectoryEntry对象:

DirectoryEntry entry = new DirectoryEntry("LDAP://test.corp");

在这段代码中,作者利用硬编码的法子把域名写进了代码。 大家怎么样精通当前计算机所利用的是哪个域名呢? 答案是:查看“我的微型计算机”的属性对话框:

图片 3

瞩目:这几个域名不断定与System.Environment.UserDomainName一样。

除开能够查看“作者的Computer”的性质对话框外,大家还足以接纳代码的法子获得当前电脑所选择的域名:

private static string GetDomainName()
{
    // 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。
    SelectQuery query = new SelectQuery("Win32_ComputerSystem");
    using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {
        foreach( ManagementObject mo in searcher.Get() ) {
            if( (bool)mo["partofdomain"] )
                return mo["domain"].ToString();
        }
    }
    return null;
}

当组织了DirectorySearcher对象后,大家便得以应用DirectorySearcher来试行对Active Directory的检索。 大家能够选拔下边包车型大巴手续来施行寻觅: 1. 安装 DirectorySearcher.Filter 提示LDAP格式筛选器,那是多个字符串。 2. 一再调用PropertiesToLoad.Add() 设置搜索进程中要物色的习性列表。 3. 调用FindOne() 方法得到搜索结果。

上边的代码演示了什么样从Active Directory中查找登陆名叫“fl45”的客户消息:

static void Main(string[] args)
{
    Console.WriteLine(Environment.UserDomainName);
    Console.WriteLine(Environment.UserName);
    Console.WriteLine("------------------------------------------------");

    ShowUserInfo("fl45", GetDomainName());
}

private static string AllProperties = "name,givenName,samaccountname,mail";

public static void ShowUserInfo(string loginName, string domainName)
{
    if( string.IsNullOrEmpty(loginName) || string.IsNullOrEmpty(domainName) )
        return;

    string[] properties = AllProperties.Split(new char[] { 'r', 'n', ',' }, 
                        StringSplitOptions.RemoveEmptyEntries);

    try {
        DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName);
        DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = "(samaccountname=" + loginName + ")";

        foreach( string p in properties )
            search.PropertiesToLoad.Add(p);

        SearchResult result = search.FindOne();

        if( result != null ) {
            foreach( string p in properties ) {
                ResultPropertyValueCollection collection = result.Properties[p];
                for( int i = 0; i < collection.Count; i++ )
                    Console.WriteLine(p + ": " + collection[i]);
            }
        }
    }
    catch( Exception ex ) {
        Console.WriteLine(ex.ToString());
    }
}

结果如下:

图片 4

在前面的代码,作者在寻觅Active Directory时,只找寻了"name,givenName,samaccountname,mail"那4个特性。 不过,LDAP还扶助更加多的习性,我们得以行使下边包车型大巴代码查看越来越多的客商音信:图片 5;)

        private static string AllProperties = @"
homemdb
distinguishedname
countrycode
cn
lastlogoff
mailnickname
dscorepropagationdata
msexchhomeservername
msexchmailboxsecuritydescriptor
msexchalobjectversion
usncreated
objectguid
whenchanged
memberof
msexchuseraccountcontrol
accountexpires
displayname
primarygroupid
badpwdcount
objectclass
instancetype
objectcategory
samaccounttype
whencreated
lastlogon
useraccountcontrol
physicaldeliveryofficename
samaccountname
usercertificate
givenname
mail
userparameters
adspath
homemta
msexchmailboxguid
pwdlastset
logoncount
codepage
name
usnchanged
legacyexchangedn
proxyaddresses
department
userprincipalname
badpasswordtime
objectsid
sn
mdbusedefaults
telephonenumber
showinaddressbook
msexchpoliciesincluded
textencodedoraddress
lastlogontimestamp
company
";

重回顶上部分

3. 得到当前系统客商名/客户组

通过 System.Environment.UserDomainName 和 System.Environment.UserName 取伏贴前客商名

对眼下系统顾客名/客户组的其他操作,可参谋

  • C# 管理 Windows 当地顾客组
  • C# 获取 Windows 客商组成员

所以,将Path.Combine(Environment.UserDomainName, Environment.UserName)与IdentityReference.Value相比较,获取当前顾客对文件夹的权限音信

详细完结如下:

 1     /// <summary>
 2     /// 检查当前用户是否拥有此文件夹的操作权限
 3     /// </summary>
 4     /// <param name="folder"></param>
 5     /// <returns></returns>
 6     public static bool HasOperationPermission(string folder)
 7     {
 8         var currentUserIdentity = Path.Combine(Environment.UserDomainName, Environment.UserName);
 9 
10         DirectorySecurity fileAcl = Directory.GetAccessControl(folder);
11         var userAccessRules = fileAcl.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)).OfType<FileSystemAccessRule>().Where(i=>i.IdentityReference.Value==currentUserIdentity).ToList();
12 
13         return userAccessRules.Any(i => i.AccessControlType == AccessControlType.Deny);
14     }

 

在ASP.NET中访问Active Directory

眼前小编在二个调控台程序中示范了拜见Active Directory的不二秘技,通过演示我们能够见到:在代码中,小编用Environment.UserName就足以得到当前客户的登入名。 但是,假如是在ASP.NET程序中,访谈Environment.UserName就很有望得不到确实客户登入名。 因为:Environment.UserName是运用WIN32API中的GetUserName获取线程相关的客户名,但ASP.NET运转在IIS中,线程相关的客户名就不必然是客户端的顾客名了。 不过,ASP.NET能够画虎不成反类犬客户情势运营,通过这种艺术才足以收获不错的结果。关于“模拟”的话题在本文的后面部分有表明。

在ASP.NET中,为了能可相信的获取登陆客户的登陆名,大家能够动用上面包车型大巴代码:

/// <summary>
/// 根据指定的HttpContext对象,获取登录名。
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static string GetUserLoginName(HttpContext context)
{
    if( context == null )
        return null;

    if( context.Request.IsAuthenticated == false )
        return null;

    string userName = context.User.Identity.Name;
    // 此时userName的格式为:UserDomainNameLoginName
    // 我们只需要后面的LoginName就可以了。

    string[] array = userName.Split(new char[] { '\' }, StringSplitOptions.RemoveEmptyEntries);
    if( array.Length == 2 )
        return array[1];

    return null;
}

在ASP.NET中运用Windows身份验证时,IIS和WindowsAuthenticationModule已经做了无数表明客商的连锁专门的学业, 就算大家可以动用前面的代码获取到用户的登陆名,但客户的别的新闻即需求我们温馨来博取。 在实质上选拔Windows身份ID明时,我们要做的事:基本上正是从Active Directory中依照顾客的登陆名获得所需的各样新闻。

比方说:小编的前后相继在运维时,还索要采纳以下与客户相关的新闻:

public sealed class UserInfo
{
    public string GivenName;
    public string FullName;
    public string Email;
}

那么,咱们能够运用这样的代码来获取所需的客商消息:图片 6;)

public static class UserHelper
{
    /// <summary>
    /// 活动目录中的搜索路径,也可根据实际情况来修改这个值。
    /// </summary>
    public static string DirectoryPath = "LDAP://" + GetDomainName();


    /// <summary>
    /// 获取与指定HttpContext相关的用户信息
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static UserInfo GetCurrentUserInfo(HttpContext context)
    {
        string loginName = GetUserLoginName(context);
        if( string.IsNullOrEmpty(loginName) )
            return null;

        return GetUserInfoByLoginName(loginName);
    }

    /// <summary>
    /// 根据指定的HttpContext对象,获取登录名。
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public static string GetUserLoginName(HttpContext context)
    {
        if( context == null )
            return null;

        if( context.Request.IsAuthenticated == false )
            return null;

        string userName = context.User.Identity.Name;
        // 此时userName的格式为:UserDomainNameLoginName
        // 我们只需要后面的LoginName就可以了。

        string[] array = userName.Split(new char[] { '\' }, StringSplitOptions.RemoveEmptyEntries);
        if( array.Length == 2 )
            return array[1];

        return null;
    }


    /// <summary>
    /// 根据登录名查询活动目录,获取用户信息。
    /// </summary>
    /// <param name="loginName"></param>
    /// <returns></returns>
    public static UserInfo GetUserInfoByLoginName(string loginName)
    {
        if( string.IsNullOrEmpty(loginName) )
            return null;

        // 下面的代码将根据登录名查询用户在AD中的信息。
        // 为了提高性能,可以在此处增加一个缓存容器(Dictionary or Hashtable)。

        try {
            DirectoryEntry entry = new DirectoryEntry(DirectoryPath);
            DirectorySearcher search = new DirectorySearcher(entry);
            search.Filter = "(SAMAccountName=" + loginName + ")";

            search.PropertiesToLoad.Add("givenName");
            search.PropertiesToLoad.Add("cn");
            search.PropertiesToLoad.Add("mail");
            // 如果还需要从AD中获取其它的用户信息,请参考ActiveDirectoryDEMO

            SearchResult result = search.FindOne();

            if( result != null ) {
                UserInfo info = new UserInfo();
                info.GivenName = result.Properties["givenName"][0].ToString();
                info.FullName = result.Properties["cn"][0].ToString();
                info.Email = result.Properties["mail"][0].ToString();
                return info;
            }
        }
        catch {
            // 如果需要记录异常,请在此处添加代码。
        }
        return null;
    }


    private static string GetDomainName()
    {
        // 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。
        SelectQuery query = new SelectQuery("Win32_ComputerSystem");
        using( ManagementObjectSearcher searcher = new ManagementObjectSearcher(query) ) {
            foreach( ManagementObject mo in searcher.Get() ) {
                if( (bool)mo["partofdomain"] )
                    return mo["domain"].ToString();
            }
        }
        return null;
    }

}

选取UserHelper的页面代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>WindowsAuthentication DEMO  - http://www.cnblogs.com/fish-li/</title>
</head>
<body>
<% if( Request.IsAuthenticated ) { %>
    当前登录全名:<%= Context.User.Identity.Name.HtmlEncode()%> <br />

    <% var user = UserHelper.GetCurrentUserInfo(Context); %>
    <% if( user != null ) { %>
        用户短名:<%= user.GivenName.HtmlEncode()%> <br />
        用户全名:<%= user.FullName.HtmlEncode() %> <br />
        邮箱地址:<%= user.Email.HtmlEncode() %>
    <% } %>    
<% } else { %>
    当前用户还未登录。
<% } %>
</body>
</html>

程序运维的作用如下:

图片 7

别的,还是可以从Active Directory查询二个名称叫memberof的特性(它与Windows客商组无关),一时候能够用它有别于客户,设计与权力相关的操作。

在准备数据持久化的表结构时,由于此时并未有“客户表”,那么我们能够直接保存客商的登陆名。 剩下的开支工作就与Forms身份认证未有太多的差距了。

回来顶上部分

动用Active Directory验证客商地方

日前介绍了ASP.NET Windows居民身份注脚,在这种格局下,IIS和WindowsAuthenticationModule为我们达成了顾客地点验证的进度。 可是,有的时候大概鉴于各样缘由,需求大家以编制程序的方法选拔Active Directory验证客户身份,譬如:在WinForm主次,可能别的的注脚逻辑。

大家不但能够从Active Directory中询问客户新闻,也得以用它来实现认证客户地点,那样便足以兑现自身的报到验证逻辑。

无论是怎么使用Active Directory,大家都要求选用DirectoryEntry和DirectorySearcher那三个目的。DirectoryEntry还提供三个构造函数可让大家输入顾客名和密码:

// 摘要:
//     初始化 System.DirectoryServices.DirectoryEntry 类的新实例。
//
// 参数:
//   Password:
//     在对客户端进行身份验证时使用的密码。DirectoryEntry.Password 属性初始化为该值。
//
//   username:
//     在对客户端进行身份验证时使用的用户名。DirectoryEntry.Username 属性初始化为该值。
//
//   Path:
//     此 DirectoryEntry 的路径。DirectoryEntry.Path 属性初始化为该值。
public DirectoryEntry(string path, string username, string password);

要兑现和煦的记名检查,就须求接纳这几个构造函数。 以下是自个儿写用WinForm写的四个登录检查的示范:

private void btnLogin_Click(object sender, EventArgs e)
{
    if( txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0 ) {
        MessageBox.Show("用户名或者密码不能为空。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    string ldapPath = "LDAP://" + GetDomainName();
    string domainAndUsername = Environment.UserDomainName + "\" + txtUsername.Text;
    DirectoryEntry entry = new DirectoryEntry(ldapPath, domainAndUsername, txtPassword.Text);

    DirectorySearcher search = new DirectorySearcher(entry);

    try {
        SearchResult result = search.FindOne();

        MessageBox.Show("登录成功。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch( Exception ex ) {
        // 如果用户名或者密码不正确,也会抛出异常。
        MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Stop);
    }
}

程序运转的成效如下:

图片 8

回去顶上部分

本文由澳门在线威尼斯官方发布于澳门在线威尼斯官方,转载请注明出处:判断用户是否对路径拥有访问权限,Windows身份认

关键词:

上一篇:中的闭包,函数式程序设计之用闭包封装数据

下一篇:没有了