ad 单点登录 java 访问权限_AD 单点登录以及windows认证详细说明

上篇博客我谈到了一些关于ASP.NET Forms身份认证方面的话题,这次的博客将主要介绍ASP.NET Windows身份认证。

Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windows身份认证也会比较方便。 方便性表现为:我们不用再设计登录页面,不用编写登录验证逻辑。而且使用Windows身份认证会有更好的安全保障。

认识ASP.NET Windows身份认证

要使用Windows身份认证模式,需要在web.config设置:

Windows身份认证做为ASP.NET的默认认证方式,与Forms身份认证在许多基础方面是一样的。上篇博客我说过:我认为ASP.NET的身份认证的最核心部分其实就是HttpContext.User这个属性所指向的对象。在接下来的部分,我将着重分析这个对象在二种身份认证中有什么差别。

在ASP.NET身份认证过程中,IPrincipal和IIdentity这二个接口有着非常重要的作用。 前者定义用户对象的基本功能,后者定义标识对象的基本功能, 不同的身份认证方式得到的这二个接口的实例也是不同的。

ASP.NET Windows身份认证是由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身份认证需要Cookie表示登录状态,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身份认证中,验证工作主要是由IIS实现的,WindowsAuthenticationModule其实只是负责创建WindowsPrincipal和WindowsIdentity而已。 顺便介绍一下:Windows 身份验证又分为“NTLM 身份验证”和“Kerberos v5 身份验证”二种, 关于这二种Windows身份认证的更多说明可查看MSDN技术文章:解释:ASP.NET 2.0 中的 Windows 身份验证。 在我看来,IIS最终使用哪种Windows身份认证方式并不影响我们的开发过程,因此本文不会讨论这个话题。

根据我的实际经验来看,使用Windows身份认证时,主要的开发工作将是根据登录名从Active Directory获取用户信息。 因为,此时不需要我们再设计登录过程,IIS与ASP.NET已经为我们准备好了WindowsPrincipal和WindowsIdentity这二个与用户身份相关的对象。

访问 Active Directory

我们通常使用LDAP协议来访问Active Directory, 在.net framework中提供了DirectoryEntry和DirectorySearcher这二个类型让我们可以方便地从托管代码中访问 Active Directory 域服务。

如果我们要在"test.corp”这个域中搜索某个用户信息,我们可以使用下面的语句构造一个DirectoryEntry对象:DirectoryEntryentry =newDirectoryEntry("LDAP://test.corp");

在这段代码中,我采用硬编码的方式把域名写进了代码。

我们如何知道当前电脑所使用的是哪个域名呢?

答案是:查看“我的电脑”的属性对话框:

42865919_1.png

注意:这个域名不一定与System.Environment.UserDomainName相同。

除了可以查看“我的电脑”的属性对话框外,我们还可以使用代码的方式获取当前电脑所使用的域名:private static stringGetDomainName()

{

// 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。SelectQueryquery =newSelectQuery("Win32_ComputerSystem");

using( ManagementObjectSearchersearcher =newManagementObjectSearcher(query) ) {

foreach( ManagementObjectmo insearcher.Get() ) {

if( (bool)mo["partofdomain"] )

returnmo["domain"].ToString();

}

}

return null;

}

当构造了DirectorySearcher对象后,我们便可以使用DirectorySearcher来执行对Active Directory的搜索。

我们可以使用下面的步骤来执行搜索:

1. 设置 DirectorySearcher.Filter 指示LDAP格式筛选器,这是一个字符串。

2. 多次调用PropertiesToLoad.Add() 设置搜索过程中要检索的属性列表。

3. 调用FindOne() 方法获取搜索结果。

下面的代码演示了如何从Active Directory中搜索登录名为“fl45”的用户信息:static voidMain(string[] args)

{

Console.WriteLine(Environment.UserDomainName);

Console.WriteLine(Environment.UserName);

Console.WriteLine("------------------------------------------------");

ShowUserInfo("fl45", GetDomainName());

}

private static stringAllProperties ="name,givenName,samaccountname,mail";

public static voidShowUserInfo(stringloginName, stringdomainName)

{

if( string.IsNullOrEmpty(loginName) ||string.IsNullOrEmpty(domainName) )

return;

string[] properties =AllProperties.Split(new char[] { '\r', '\n', ','},

StringSplitOptions.RemoveEmptyEntries);

try{

DirectoryEntryentry =newDirectoryEntry("LDAP://"+domainName);

DirectorySearchersearch =newDirectorySearcher(entry);

search.Filter ="(samaccountname="+loginName +")";

foreach( stringp inproperties )

search.PropertiesToLoad.Add(p);

SearchResultresult =search.FindOne();

if( result !=null) {

foreach( stringp inproperties ) {

ResultPropertyValueCollectioncollection =result.Properties[p];

for( inti =0; i

Console.WriteLine(p +": "+collection[i]);

}

}

}

catch( Exceptionex ) {

Console.WriteLine(ex.ToString());

}

}

结果如下:

42865919_2.png

在前面的代码,我在搜索Active Directory时,只搜索了"name,givenName,samaccountname,mail"这4个属性。 然而,LDAP还支持更多的属性,我们可以使用下面的代码查看更多的用户信息:private static stringAllProperties =@"

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

";

在ASP.NET中访问Active Directory

前面我在一个控制台程序中演示了访问Active Directory的方法,通过示例我们可以看到:在代码中,我用Environment.UserName就可以得到当前用户的登录名。 然而,如果是在ASP.NET程序中,访问Environment.UserName就很有可能得不到真正用户登录名。 因为:Environment.UserName是使用WIN32API中的GetUserName获取线程相关的用户名,但ASP.NET运行在IIS中,线程相关的用户名就不一定是客户端的用户名了。 不过,ASP.NET可以模拟用户方式运行,通过这种方式才可以得到正确的结果。关于“模拟”的话题在本文的后面部分有说明。

在ASP.NET中,为了能可靠的获取登录用户的登录名,我们可以使用下面的代码:///

///根据指定的HttpContext对象,获取登录名。///

///

/// public static stringGetUserLoginName(HttpContextcontext)

{

if( context ==null)

return null;

if( context.Request.IsAuthenticated ==false)

return null;

stringuserName =context.User.Identity.Name;

// 此时userName的格式为:UserDomainName\LoginName

// 我们只需要后面的LoginName就可以了。string[] array =userName.Split(new char[] { '\\'}, StringSplitOptions.RemoveEmptyEntries);

if( array.Length ==2)

returnarray[1];

return null;

}

在ASP.NET中使用Windows身份认证时,IIS和WindowsAuthenticationModule已经做了许多验证用户的相关工作, 虽然我们可以使用前面的代码获取到用户的登录名,但用户的其它信息即需要我们自己来获取。 在实际使用Windows身份认证时,我们要做的事:基本上就是从Active Directory中根据用户的登录名获取所需的各种信息。

比如:我的程序在运行时,还需要使用以下与用户相关的信息:public sealed classUserInfo{

public stringGivenName;

public stringFullName;

public stringEmail;

}

那么,我们可以使用这样的代码来获取所需的用户信息:public static classUserHelper{

///

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

///

///获取与指定HttpContext相关的用户信息///

///

/// public staticUserInfoGetCurrentUserInfo(HttpContextcontext)

{

stringloginName =GetUserLoginName(context);

if( string.IsNullOrEmpty(loginName) )

return null;

returnGetUserInfoByLoginName(loginName);

}

///

///根据指定的HttpContext对象,获取登录名。///

///

/// public static stringGetUserLoginName(HttpContextcontext)

{

if( context ==null)

return null;

if( context.Request.IsAuthenticated ==false)

return null;

stringuserName =context.User.Identity.Name;

// 此时userName的格式为:UserDomainName\LoginName

// 我们只需要后面的LoginName就可以了。string[] array =userName.Split(new char[] { '\\'}, StringSplitOptions.RemoveEmptyEntries);

if( array.Length ==2)

returnarray[1];

return null;

}

///

///根据登录名查询活动目录,获取用户信息。///

///

/// public staticUserInfoGetUserInfoByLoginName(stringloginName)

{

if( string.IsNullOrEmpty(loginName) )

return null;

// 下面的代码将根据登录名查询用户在AD中的信息。

// 为了提高性能,可以在此处增加一个缓存容器(Dictionary or Hashtable)。try{

DirectoryEntryentry =newDirectoryEntry(DirectoryPath);

DirectorySearchersearch =newDirectorySearcher(entry);

search.Filter ="(SAMAccountName="+loginName +")";

search.PropertiesToLoad.Add("givenName");

search.PropertiesToLoad.Add("cn");

search.PropertiesToLoad.Add("mail");

// 如果还需要从AD中获取其它的用户信息,请参考ActiveDirectoryDEMOSearchResultresult =search.FindOne();

if( result !=null) {

UserInfoinfo =newUserInfo();

info.GivenName =result.Properties["givenName"][0].ToString();

info.FullName =result.Properties["cn"][0].ToString();

info.Email =result.Properties["mail"][0].ToString();

returninfo;

}

}

catch{

// 如果需要记录异常,请在此处添加代码。}

return null;

}

private static stringGetDomainName()

{

// 注意:这段代码需要在Windows XP及较新版本的操作系统中才能正常运行。SelectQueryquery =newSelectQuery("Win32_ComputerSystem");

using( ManagementObjectSearchersearcher =newManagementObjectSearcher(query) ) {

foreach( ManagementObjectmo insearcher.Get() ) {

if( (bool)mo["partofdomain"] )

returnmo["domain"].ToString();

}

}

return null;

}

}

使用UserHelper的页面代码:

WindowsAuthentication DEMO - http://www.cnblogs.com/fish-li/
用户短名:
用户全名:
邮箱地址:

当前用户还未登录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

index加载显示servlet数据_[WEB篇]-JavaWeb基础与应用-02-Servlet开发

JavaWeb基础与应用2.Servlet开发Servlet是sun公司提供的一门用于开发动态web资源的技术。Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:编写一个Java类&…

Linux命令之stty

用途说明 stty命令用于显示和修改终端行设置(change and print terminal line settings)。 常用参数 stty命令不带参数可以打印终端行设置,加上-a参数可以打印得更详细些。 stty size可以显示终端的大小,即行数和列数。 stty命令还…

本机速度文件支持的“纯” Java大数据存储

动机 所有这一切始于意识到我买不起足够大的计算机。 音频处理需要大量的内存。 Audacity是一款出色的免费音频处理器,它使用文件支持的存储系统对其进行管理。 这是解决此类问题的常用方法,在这些问题中,我们存储了大量信息,并希…

element ui后台html_GitHub上10个开源且优秀的后台管理系统UI面板

作者:SevDotwww.jianshu.com/p/3bc7404af887Web 开发中几乎的平台都需要一个后台管理,但是从零开发一套后台控制面板并不容易,幸运的是有很多开源免费的后台控制面板可以给开发者使用,那么有哪些优秀的开源免费的控制面板呢&#…

mysql 唯一记录_mysql选择唯一记录

我有以下查询:select * from members,subscriptionswhere members.MemberID subscriptions.MemberIDand subscriptions.Year 2009and members.ASSCID 15and subscriptions.Untildate between $2009-01-01 and 2009-12-31order by members.Memberlastname会员支付…

JAVA第七次作业

《Java技术》第七次作业 (一)学习总结 1.写出事件处理模型中的几个关键词,并通过具体代码实例说明你对事件处理模型的理解。 WindowListener:窗体事件,专门处理窗体的事件监听口,窗体的所有变化都可以使用此…

java时间格式转js_使用jquery或java脚本将日期时间转换为rfc3339格式

您的要求似乎微不足道,还有更多吗?这是显而易见的答案:function formatTimestring(s) {var b s.split(/[\\/:]/);return b[2] b[1] b[0] \T\ b[3] b[4] \00\ \Z\}alert(formatTimestring(\08/09/2010:12:00\) //20100908T120000Z);如…

输出以下图案菱形7行_春夏格子图案超流行,三木的一款格子连衣裙,带来田园少女风...

春夏搭配中,增添了华丽格子图案搭配,从经典的格子裙子,到衬衫裙等。根据搭配不同而成为不同风格。所以,这一次,重点介绍格子裙和长衬衫的几种种搭配。格子裙子的春夏搭配推荐LOOK:1 [格子褶皱裙子棕色T恤]的…

asp.net FileUpload上传文件夹并检测所有子文件

1.在FileUpload控件添加一个属性 webkitdirectory""就可以上传文件夹了 <asp:FileUpload ID"FileUpload1" runat"server" webkitdirectory"" />2.检测文件夹下所有子文件 string DirectoryName FileUpload1.PostedFile.FileNam…

使用Project Jigsaw的JDK 9 Early Access上的Eclipse IDE

几周前&#xff0c;我写了关于在Java 9上运行Eclipse Neon的文章 &#xff08;尽管&#xff0c;我在帖子标题中错误地和令人尴尬地留下了“火星”&#xff09;。 值得注意的是&#xff0c;我列出的步骤也适用于带有Project Jigsaw &#xff08;Java模块化&#xff09;构建的JDK…

火狐配置java_java selenium+firefox环境搭建

已经成功搭建的版本关系&#xff1a;FireFox45selenium3.141.59 geckodriver 0.21.0启动浏览器后空白页&#xff1a;浏览器版本太高Firefox历史版本geckodriver驱动版本https://github.com/mozilla/geckodriver/releasesselenium maven地址org.seleniumhq.seleniumselenium-ja…

arduino蜂鸣器_板卡推荐BPIUNO32 arduino 开发板,支持webduino与arduino应用

BPI:UNO32(也称为BPI-UNO32&#xff0c;被称为BPI UNO32)是一个带有Xtensa 32位LX6的单/双核心处理器的嵌入式系统的ESP32。支持Webduino和arduino的功能。BPI-UNO32使用的是esp-WROOM32&#xff0c;MCU。ESP32是一种集成2.4 GHz Wi-Fi和蓝牙双模式的单芯片解决方案。该公司的4…

Perl sendmail

introduction of sendmailexamplesend mail to multi-receiver转载于:https://www.cnblogs.com/david-wei0810/p/6846515.html

java 7.0 特性_JDK7.0语法新特性

JDK7.0语法新特性1&#xff0c;菱形语法(泛型实例化类型自动推断)List list new ArrayList<>(); // <>这个真的很像菱形2&#xff0c;在目前版本中&#xff0c;不可具体化的泛型(任意类型)可变参数&#xff0c;在编译时&#xff0c;会在调用处产生警告&#xff0c…

Unity优化之GC——合理优化Unity的GC (难度3 推荐5)

原文链接&#xff1a;http://www.cnblogs.com/zblade/p/6445578.html 最近有点繁忙&#xff0c;白天干活晚上抽空写点翻译&#xff0c;还要运动&#xff0c;所以翻译工作进行的有点缓慢 。 本文续接前面的unity的渲染优化&#xff0c;进一步翻译Unity中的GC优化&#xff0c;英文…

centos重置系统_双系统下Linux系统无法启动及其引导丢失之解决

背景介绍: 很久很久以前, 我在 NewSurfacePro(SP5) 里插了一张 128G 内存卡, 费力九牛二虎之力在上面装了 Deepin, 后来在某次不知道是 Windows 还是 Deepin 更新后, Deepin 启动时总要发生一个极具 Linux 特色的启动错误, witch 似乎在我树莓派上出现过, 折腾了很久也没好, 就…

Java 7和Java 8之间的细微自动关闭合同更改

Java 7的try-with-resources语句和与该语句一起使用的AutoCloseable类型的一个不错的功能是&#xff0c;静态代码分析工具可以检测到资源泄漏。 例如&#xff0c;Eclipse&#xff1a; 具有以上配置并尝试运行以下程序时&#xff0c;您将收到三个警告&#xff1a; public stat…

reduce python3_更少循环?看看这3个Python函数

原标题&#xff1a;更少循环&#xff1f;看看这3个Python函数 全文共1146字&#xff0c;预计学习时长5分钟图源&#xff1a;wired 诞生于1991年的Python&#xff0c;这几年突然火了。简历上有了Python&#xff0c;就业竞争力瞬间提升&#xff0c;甚至一些小学教材上都出现了Pyt…

java list compareto_Java,如何使用compareTo对Arraylist进行排序

我试图弄清楚如何使用可比较的方式对ArrayList进行排序,我的代码如下所示&#xff1a;public class playerComparsion{public static void main(String[] args){ArrayList list new ArrayList();Player p1 new Players(1,92,Zlatan);Player p2 new Players(2,92,Hazard);Pla…

java图片上传(mvc)

最近有开始学起了java,好久没写文章了,好久没来博客园了。最近看了看博客园上次写的图片上传有很多人看&#xff0c;今天在一些篇关于java图片上传的。后台接收用的是mvc。不墨迹了&#xff0c;直接上图。 先看目录结构。idea开发。 一、图片上传还是使用的这款jq插件。前端部署…