SharePoint Claim base authentication EnsureUser 不带claim(i:0#.w|)user Failed
环境信息:
带有Form base authentication(FBA)、Active Directory Federation Services(ADFS)、以及windows Authentication的混合认证的SharePoint环境。
问题具体描述:
在该环境中,调用EnsureUser添加一个普通的AD user,sharepoint 会throw "The specified user userLoginName could not be found.",当然此处的user login name是不带有claim(i:0#.w|),具体如下图显示:
查看问题原因过程:
其实在刚刚看到该问题时,我首先查看了sharepoint log,但是log中并没有发现什么有用的信息,在这之后我测试了对带有claim(i:0#.w|)的user login name进行EnsureUser 操作,发现对于带有claim(i:0#.w|)的user 是可以正常添加到sharepoint 中的,通过这点,我们基本上可以断定问题应该是混合认证导致的,但是仅仅是这样当然是不够的,我们需要分析出问题的根本原因,为什么带有claim的user 能够正常添加到sharepoint环境中,而不带有claim的却会throw exception呢?
问题分析到这里单单调用SharePoint API已经无法帮助我们了,这时就需要祭出神器:Reflector 来分析EnsureUser 这个方法,查看sharepoint 内部的逻辑,以查找该问题的根本原因,具体的分析过程就不在这里赘述了,无非就是静下心来啃微软的Code。
这里简单讲解下在EusuerUser时claim对于UserLoginName的意义:
如果UserLoginName带有claim(i:0#.w|domain\userName):EnsureUser方法内部会根据该claim生成SPClaim对象,该对象指定了provider的类型,因此,SharePoint可以通过SPClaim对象对当前环境中可用的provider进行过滤,只有符合SPClaim.ClaimType的provider,才会尝试获取user信息。
如果UserLoginName没有claim(domain\userName):由于没有claim,无法创建 SPClaim对象,那么只能根据EnsureUser方法内部传入的SPPrincipalType(EnsureUser方法内部传入的是SPPrincipalType.SecurityGroup|SPPrincipalType.User)来对provider进行过滤,只要支持这两种type的provider都会尝试获取user信息,而通过SPClaim过滤provider显然要比通过SPPrincipalType过滤要精确的多(这里有一点需要注意:对于大批量的EnsureUser,建议使用带有cliam的userLoginName格式,这样可以更精确的定位provider,进而更少的调用provider resolve user,进而提高EnsureUser的效率。
说了这么多貌似和我们的问题没有什么关系,我们要添加的user就是一个普普通通的ad user,windows authentication对应的provider应该是可以获取到这个user的,但是为什么却会throw exception呢?
我们认为windows authentication对应的provider可以通过user login name获取到user信息,而SharePoint实际上并没有获取到user信息,既然与我们认为的不一致,那就有必要写程序验证一下到底能不能获取到这个user的信息了,通过之前分析EnsuerUser 方法内部的代码,我找到了SharePoint内部调用provider resolve user的方法,见截图:
该方法为EnsureUser内部调用的方法,而它的作用就是调用provider的Resolve方法来获取user,这样问题就简单了,我们反射模拟下该方法来确认provider能否通过login name取到user就行了,反射模拟的代码比较简单,这里就不做赘述了,直接上结果:
注意绿色部分为provier获取到的user信息,通过结果我们可以发现windows authentication对应的provider实际上已经获取到了相关的user信息,并且返回的user login name已经是带有claim的格式了,既然获取到了user信息为什么EnsureUser 方法会不好使呢?实际上问题到这里就比较明显了,通过结果,我们会发现不仅仅是windows authentication对应的provider获取到了user 信息,ADFS对应的provider也同样的获取到了user的信息(这是ADFS正常的正常逻辑,对于ADFS来说不论查询的user是否存在,都会返回一个user,如果想避免该问题,可以配置LDAP,具体配置方法见传送门:LDAP配置方法),既然我们认定是混合认证导致不带有claim的AD user无法正常添加,那么会不会是因为ADFS也获取到了user信息导致的问题呢?,我们再回头看看EnsureUser方法内部的逻辑,应该不难找到这个方法:
注意截图中的两个红框,第一个红框实际上就是我们刚才反射模拟的方法,该方法把最终获取到的user相关信息的结果保存在entityArray中,而下一个红框实际上是对entityArray的一些特殊处理,通过这个特殊处理我们不难看出只有entityArray.lenth==1时,才会将provider获取到的user信息转换成SPPrincipalInfo对象,而如果不满足红框中的if条件,那么就会执行红框下的if语句(if(info == null) info=user;),但是实际上user是null,这样ResolvePrincipalClaims方法获取到的info对象也是一个unll值,自然也就无从谈起将user添加到SharePoint中了,进而会throw "The specified user userLoginName could not be found."。
总结一下该问题的原因:该问题实际上是由于SharePoint环境中存在多种认证方式,导致在调用API添加user时,SharePoint通过各个provider对于同一个user name获取到了多个user,但是SharePoint并不知道我们到底想将哪个user添加到SharePoint中,因此倒不如哪个user也不添加,进而导致添加user失败。
PS:该问题为本人研究结果,如果有什么错漏之处,欢迎各位大大指正^_^
SharePoint Claim base authentication EnsureUser 不带claim(i:0#.w|)user Failed的更多相关文章
- [SharePoint]SharePoint Claim base Authentication的一个比较好的介绍
User identity in AD DS is based on a user account. For successful authentication, the user provides ...
- SharePoint 2010 Form Authentication (SQL) based on existing database
SharePoint 2010 表单认证,基于现有数据库的用户信息表 本文主要描写叙述本人配置过程中涉及到的步骤,仅作为參考,不要仅限于此步骤. 另外本文通俗易懂,适合大众口味儿. I. 开启并配置基 ...
- Authentication to host '***‘' for user 'root' using method 'mysql_native_password' failed with message: Reading from the stream has failed.
如下场景: 一个页面中需要用户填入文字信息,并上传图片,上传图片是单独调用上传文件接口的,当用户上传图片后,马上点保存,就会报错. Authentication to host '***‘' for ...
- Exception in thread "main" java.lang.UnsupportedClassVersionError: com/google/common/base/Function : Unsupported major.minor version 52.0的解决办法(图文详解)
不多说,直接上干货! 问题详情 Exception in thread "main" java.lang.UnsupportedClassVersionError: com/goo ...
- .NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理
.NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制 基于claims 角色控制 基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例 ...
- Oracle取月份-不带前面的0
出处:http://www.2cto.com/database/201208/145611.html 今天碰到只要取月份和天数,如果月份前面有0要去掉0.比如说2010-01-08 ,需要的结果是 ...
- SharePoint 2016 安装 Cumulative Update for Service Bus 1.0 (KB2799752)报错
前言 SharePoint 服务器场安装workflow manager 1.0的时候,报下面的错误,搜了很多博客都没有解决.然后,灵机一动,下载了一个英文版的累计更新包,安装成功了. SharePo ...
- ({i:0#.w|nt authority\iusr})Sharepoint impersonates the IUSR account and is denied access to resources
This hotfix makes a new application setting available in ASP.NET 2.0. The new application setting is ...
- 开放Fedora10自带的MySQL5.0.67的对外数据库服务
MySQL5.0.67是Fedora10安装时的可选项目. 测试的笔记本IP为192.168.0.100,作为安装Fedora10和MySQL5.0.67的服务器BlackMachine的IP地址为1 ...
随机推荐
- Android教程收集贴
Loader & REST Rest Loader Tutorial [github源码] [源码演示] [github作者主页] Twitter Timeline Sample for An ...
- 用SVN check out项目后第三方库丢失
曾经用Cornerstone check out 一份项目下来,但其中第三方.a库始终丢失,项目报错,研究后找到了以下解决方法: 首先,Xcode默认忽略.a 文件.所以无法提交到svn服务器,但是很 ...
- ubuntu 16.04 安装nodejs
经过几天的尝试,终于装好了: 1. nodejs官方推荐一下安装方式: NodeSource的二进制安装脚本NodeSource Using Ubuntu curl -sL https://deb.n ...
- Oracle分区索引
索引与表类似,也可以分区: 分区索引分为两类: Locally partitioned index(局部分区索引) Globally partitioned index(全局分区索引) 下面就来详细解 ...
- APUE学习之多线程编程(三):线程属性、同步属性
一.线程属性 可以使用pthread_attr_t结构修改线程默认属性,并这些属性和创建的线程练习起来,可以使用pthread_att_init函数初始化pthread_attr_t结构,调 ...
- tomcat安装后,本地可以访问,远程不能访问
问题描述:tomcat安装后,在本地可以使用本地IP地址.localhost可以访问,但是在远程却不能访问. 使用工具:无. 解决方法:关闭服务器端的"公用网络防火墙"即可.
- zip命令的基本用法
zip命令的基本用法是: zip [参数] [打包后的文件名] [打包的目录路径] linux zip命令参数列表: -a 将文件转成ASCII模式 -F 尝试修复损坏的压缩文件 -h 显示帮助界面 ...
- Java实现office文档与pdf文档的在线预览功能
最近项目有个需求要java实现office文档与pdf文档的在线预览功能,刚刚接到的时候就觉得有点难,以自己的水平难以在三四天做完.压力略大.后面查找百度资料.以及在同事与网友的帮助下,四天多把它做完 ...
- 揭开C++类中虚表的“神秘面纱”
C++类中的虚表结构是C++对象模型中一个重要的知识点,这里咱们就来深入分析下虚表的在内存中的结构. C++一个类中有虚函数的话就会有一个虚表指针,其指向对应的虚表,一般一个类只会有一个虚表,每个虚表 ...
- Linux下的串口编程及非阻塞模式
本篇介绍了如何在linux系统下向串口发送数据.包括read的阻塞和非阻塞.以及select方法. 打开串口 在Linux系统下,打开串口是通过使用标准的文件打开函数操作的. #include < ...