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类&…

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

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

JAVA第七次作业

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java图片上传(mvc)

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

appengine_Google AppEngine:任务队列API

appengine任务队列 com.google.appengine.api.taskqueue 使用任务队列,用户可以发起一个请求,以使应用程序执行此请求之外的工作。 它们是进行后台工作的强大工具。 此外,您可以将工作组织成小的离散单元(任务)。 然后…

Android studio Error occurred during initialization of VM 问题解决

最近开发导入其他Android项目遇见的问题,如下图: 解决办法: 将org.gradle.jvmargs的值该为521(堆内存分配过高导致) 备忘,希望能帮助到大家转载于:https://www.cnblogs.com/yunfang/p/6857096.html

滑动窗口限流 java_Spring Boot 的接口限流算法优缺点深度分析

点击上方蓝色字体,选择“标星公众号”优质文章,第一时间送达上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家(已修复)下一篇:昨天分享资料不小心把百度网盘深处的秘密泄露了(已修复)转自: loubobooo原文&am…

mips j指令_MIPS的基本实现

MIPS核心指令集:指令集概括为3个指令类:存储器访问指令类lw,sw等2. 算术逻辑指令类add,sub等3. 转移指令类beg,J等指令的共同性取指令,送PC值给Memory;根据指令内容读取寄存器内容;除…

腾讯管家去除桌面快捷小图标

找了大半天,原来腾讯管家也可以: 废话不多说,动手实践吧。。。。。 打开电脑管家——电脑诊所——桌面图标——【去掉快捷方式小箭头】 就这样轻松的实现了,赶快试试吧! 转载于:https://www.cnblogs.com/yjq520/p/6858…

argparse模块_Argparse:一个具体案例教会你python命令行参数解析

问题描述:现有一个用于数据格式转换的py脚本(多转一),执行时通过命令行传入一系列的参数控制其具体运行方式,使满足以下要求:1. 必须传入需要处理的原始数据文件名2. 可以指定输入文件的格式,若没有指定则使用默认值&a…

Eclipse中src/main/resources配置文件启动问题

项目pom文件有做修改如下的时候,还没有进行mvn clean install 启动test项目中的appcontext会 可以手动清空 然后就可以了。 出现如下问题的原因是 配置文件默认输出到target/classes 下 项目启动默认也会找该目录下的配置文件 其实这里pom文件拷贝配置文件只是用于读…

仍然不安全:变成了Java 9功能的Java 6中的主要错误

sun.misc.Unsafe的未来将如何发展? 随着2015年即将结束,我们认为这将是对Java社区过去一年中最热门辩论之一进行尸检的好机会。 通过查看标题,您中的大多数人可能已经开始在口腔中产生酸味并在肠道中产生愤怒的感觉,但是如果您错…

camvid数据集使用方法_使用PyTorch处理CIFAR10数据集并显示

在训练图像分类的时候,我们通常会使用CIFAR10数据集,今天就先写一下如何展示数据集的图片及预处理。第一部分代码,展示原始图像:import numpy as npimport torch#导入内置cifarfrom torchvision.datasets import cifar#预处理模块…