文档章节

SharePoint 2013自定义Providers在基于表单的身份验证(Forms-Based-Authentication)中的应用

 木宛城主
发布于 2015/03/02 19:42
字数 1451
阅读 4
收藏 0
点赞 0
评论 0

 

由于项目的需要,登录SharePoint Application的用户将从一个统一平台中获取,而不是从Domain中获取,所以需要对SharePoint Application的身份验证(Claims Authentication Types)进行更改,即采用更加灵活的混合模式登录:Windows Authentication和Forms Based Authentication。故本篇博客将着重笔墨去介绍SharePoint 2013自定义Providers在基于表单的身份验(Forms-Based-Authentication)中的应用。

更改身份验证

首先需要了解的一点事,怎样去更改指定的Web Application 的身份验证。进入SharePoint 2013 Central Administration-àApplication Management-àManage Web Applications-àAuthentication Providers,即如下所示:

如截图所示那样,启用了FBA之后,需要我们提供自定义的Menbership Provider和Role Provider。

创建Membership Provider和Role Provider

这儿我选择创建一个Class Library,当然你也可以直接创建一个SharePoint 2013 Empty Project,注意不管是哪种,最终都需要把Assembly 注册/安装 到GAC里

  • 如果是创建了SharePoint Project,要安装Assembly到GAC,直接部署就行。
  • 如果是创建了Class Library,需要有两个步骤1).Sign the assembly(右键项目-àProperty-àSigning),2)gacutil /i "<assembly path/assembly name.dll>",如下所示(使用VS Command Tool):

获取Strong Name Key File

安装Assembly到GAC

对于.NET 4.0以上的Assembly,GAC位于C:\Windows\Microsoft.NET\assembly。.NET 3.5 GAC在C:\Windows\assembly,所以别找错地方。Assembly成功注册到GAC后,最好IISReset下。

接着,创建相关的Provider,分别继承MembershipProviderRoleProvider即可。

  •  自定义MembershipProvider,主要代码如下:
public class FBA_CustomRoleProvider : MembershipProvider
    {
        #region 重写的方法

        private MembershipUserCollection employees;
        private void generateUsers()
        {

            employees = new MembershipUserCollection();
            employees.Add(new MembershipUser(this.Name, "Jack Chen", "JackChen", "Jack@Chen.com", "What your Name?", "I am Jack", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));
            employees.Add(new MembershipUser(this.Name, "Bruce Li", "BruceLi", "BruceLi@Li.com", "How are u?", "How old are u", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));
            employees.Add(new MembershipUser(this.Name, "Eyes Wang", "EyesWang", "EyesWang@Mintcode.com", "What the hell?", "what the fuck", true, false, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today, DateTime.Today));

        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            if (employees == null) generateUsers();
            MembershipUserCollection returnFoundUsers = new MembershipUserCollection();

            (employees.Cast<MembershipUser>().

                Where(membershipUser => membershipUser.UserName.ToLowerInvariant().Contains(usernameToMatch.ToLowerInvariant())))

                .ToList().ForEach(returnFoundUsers.Add);

            totalRecords = returnFoundUsers.Count;
            return returnFoundUsers;
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {

            if (employees == null) generateUsers();
            totalRecords = employees.Count;
            return employees;
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {

            if (employees == null) generateUsers();
            IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.UserName == username);
            return usersFound.FirstOrDefault();
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {

            if (employees == null) generateUsers();

            IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.ProviderUserKey.ToString() == providerUserKey.ToString());

            return usersFound.FirstOrDefault();
        }

        public override string GetUserNameByEmail(string email)
        {
            if (employees == null) generateUsers();

            IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.Email.ToLowerInvariant() == email.ToLowerInvariant());

            MembershipUser user = usersFound.FirstOrDefault();


            if (user != null)

                return user.UserName;

            else

                return null;
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {

            if (employees == null) generateUsers();
            MembershipUserCollection returnFoundUsers = new MembershipUserCollection();

            (employees.Cast<MembershipUser>().

             Where(membershipUser => membershipUser.Email.ToLowerInvariant().Contains(emailToMatch.ToLowerInvariant())))

                .ToList().ForEach(returnFoundUsers.Add);

            totalRecords = returnFoundUsers.Count;

            return returnFoundUsers;

        }

        public override bool ValidateUser(string username, string password)
        {
            //return true;
            if (employees == null) generateUsers();

            IEnumerable<MembershipUser> usersFound = employees.Cast<MembershipUser>().Where(membershipUser => membershipUser.UserName == username);
            MembershipUser user = usersFound.FirstOrDefault();

            if (user != null)
            {

                if (string.IsNullOrEmpty(password))
                {

                    return false;

                }

                else
                {

                    return true;

                }

            }

            else

                return false;
        }
        #endregion
}
  • 自定义Role Provider,如下所示:
public class FBA_CustomMembershipProvider:RoleProvider
    {
       public override string ApplicationName { get; set; }

        //所有角色
        private string[] m_AllRoles = { "Developer", "Administrator", "Designer", "Architect ", "UI" };
    
        private string[,] m_RolesForUser = new string[,] {

            {"Eyes Wang", "Developer"},

            {"Bruce Li","Administrator"},

            {"Jack Chen","Designer,Architect"},

        };
                
        /// <summary>
        /// 获取全部角色
        /// </summary>
        /// <returns></returns>
        public override string[] GetAllRoles()
        {

            return m_AllRoles;

        }
        
        /// <summary>
        /// 根据User得到其相关的角色
        /// </summary>
        /// <param name="username"></param>
        /// <returns></returns>
        public override string[] GetRolesForUser(string username)

        {
            List<string> roles = new List<string>();
            for (int i = 0; i <= m_RolesForUser.GetUpperBound(0); i++)
            {

                if (m_RolesForUser[i, 0] == username)
                {
                    roles = m_RolesForUser[i, 1].Split(',').ToList<string>();
                }

            }
            return roles.ToArray();
        }

            /// <summary>
            /// 根据角色获取其绑定的用户
            /// </summary>
            /// <param name="rolename"></param>
            /// <returns></returns>
          public override string[] GetUsersInRole(string rolename)
          {

              List<string> users = new List<string>();
              for (int i = 0; i <= m_RolesForUser.GetUpperBound(0); i++)
               {
                   List<string> userRoles = m_RolesForUser[i, 1].Split(',').ToList<string>();
                   if (userRoles.Where(userRole => userRole == rolename).Count() > 0)
                  {

                     users.Add(m_RolesForUser[i, 0]);
                  }

              }
              return users.ToArray();
           }


         public override bool IsUserInRole(string username, string rolename)
         {

              List<string> usersForRole = GetUsersInRole(rolename).ToList();
              if (usersForRole.Where(userName => userName == username).Count() > 0)
              {
                  return true;
              }

              else
              {
                  return false;
              }

         }

        public override bool RoleExists(string rolename)
        {

             bool roleExsists = m_AllRoles.ToList().Where(roleName => roleName == rolename).Count() > 0;
             return roleExsists;
        }

        public override string[] FindUsersInRole(string rolename, string usernameToMatch)
        {

            List<string> users = GetUsersInRole(rolename).ToList<string>();
            List<string> foundUsers = users.Where(userName => userName.ToLowerInvariant().Contains(usernameToMatch.ToLowerInvariant())).ToList<string>();
            return foundUsers.ToArray();
       }
}
  • 自定义的Provider成功安装到GAC之后,接着修改web.config。注意需要修改3个地方,Web Application Config、SharePoint Central Administration Config、SecurityTokenServiceApplication,其路径如果记不住的话,打开IIS,浏览即可,即如下所示:

修改Web Config

Web Config需要Assembly的Public Key Token,可以使用VS Command Tool来获取:

  • 首先修改Web Application的Web Config,找到其Membership节点,将以下代码复制进:
<membership defaultProvider="i">
      <providers>
        <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomMembershipProvider" type="Eyes.CustomProvider.FBA_CustomRoleProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </membership>
    <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
      <providers>
        <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomRoleProvider" type="Eyes.CustomProvider.FBA_CustomMembershipProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </roleManager>
  • 接着修改SharePoint Central Administration的Web Config,
<membership defaultProvider="i">
      <providers>
        <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomMembershipProvider" type="Eyes.CustomProvider.FBA_CustomRoleProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </membership>
    <roleManager>
      <providers>
        <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomRoleProvider" type="Eyes.CustomProvider.FBA_CustomMembershipProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </roleManager>
  • 然后修改SecurityTokenSeriveApplication的Web Config,
<system.web>
     <membership defaultProvider="i">
      <providers>
        <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomMembershipProvider" type="Eyes.CustomProvider.FBA_CustomRoleProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </membership>
    <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
      <providers>
        <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
        <add name="CustomRoleProvider" type="Eyes.CustomProvider.FBA_CustomMembershipProvider,Eyes.CustomProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c4a0ffa664cbc06c" />
      </providers>
    </roleManager>
  </system.web>
  • 最后将Web Application的Authentication Type修改为混合模式,如下所示

分配用户并测试

成功为Web Application创建了自定义的Provider之后,接着就是测试是否成功。如添加访问用户,可以如下图操作所示:

搜索用户,如下图所示:

访问Site,提示混合登录模式,如下图所示:

登录成功后显示信息:

小结

当以Windows Authentication注销时,会发生错误(查阅日志后报错信息encodeValue不能为空)。我猜是没清理Session,查了很多资料,发现这是个别现象。不知道最新的SharePoint 2013 Updates有没有解决这个问题。我的版本是SharePoint 2013 Server(原始版本,从未更新过)。如果解决的话,劳烦各位朋友告诉我一下。点击代码下载

 

© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 222
码字总数 199010
作品 0
黄浦
《Pro ASP.NET MVC 3 Framework》学习笔记之三十四 【验证与授权】

使用windows验证(Using Windows Authentication) 在软件术语里面,验证的意思是测定身份。这个跟授权是完全分开的,授权是让合适的人做合适的事情,授权通常在验证之后发生。ASP.NET的验证功...

mszhangxuefei ⋅ 2012/06/15 ⋅ 0

Video : 将使用AD认证的SharePoint网站配置为表单方式登录

SharePoint网站默认是使用Active Directory集成认证,但如果是用于Internet场景,那么由于难以为访问用户建立AD帐号,解决方法通常是将SharePoint网站配置成使用Forms认证,在一个自定义的数...

余二五 ⋅ 2017/11/22 ⋅ 0

sharepoint2010 升级到 sharepoint2013注意事项

将一个SharePoint 2010站点集升级到SharePoint 2013具体步骤如下: 1) 先将你的SharePoint 2010原先的一些解决方案(wsp)安装到SharePoint 2013上。当然有些wsp你需要升级,这个我会在后期介绍...

yuxye ⋅ 2015/12/19 ⋅ 0

基于MVC的优点Advantages of an MVC-Based Web Application

ASP.NET MVC 框架具有以下优点: 它很容易通过将应用程序划分为模型、 视图和控制器管理的复杂性。 它不使用视图状态或基于服务器的窗体。这使得 MVC 框架特别适合开发人员想要完全控制应用程...

donny945 ⋅ 2015/07/03 ⋅ 0

ASP.NET 配置节架构

ASP.NET 配置节架构包含控制 ASP.NET Web 应用程序行为的元素。如果为属性指定了默认值,则该默认值是在 Machine.config 文件中设置的,该文件的路径是 systemroot/Microsoft.NET/Framework...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

Microsoft Enterprise Library 5.0 系列教程(六) Security Application Block

开发人员经常编写需要安全功能的应用程序。这些应用程序通常需要执行一系列不同的安全操作,而且它们还经常与不同的基础安全提供程序(如 Microsoft Active Directory 目录服务、授权管理器、...

老朱教授 ⋅ 2017/10/08 ⋅ 0

在ASP.NET中如何用C#.NET实现基于表单的验证

这篇文章引用到了Microsoft .NET类库中的以下名空间: System.Data.SqlClient System.Web.Security ------------------------------- 任务: 摘要: 1.要求...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

web.config文件详解

(一).Web.Config是以XML文件规范存储,配置文件分为以下格式 1.配置节处理程序声明 特点: 位于配置文件的顶部,包含在标志中。 2.特定应用程序配置 特点: 位于中。 可以定义应用程序的全局常...

晨曦之光 ⋅ 2012/03/09 ⋅ 0

[本周] 就来说说Asp.net 身份验证、授权

[本周]如约而至;时间是争取来的,这回的[本周]是把若干零碎的时间利用起来成文的,完成对Asp.net身份验证、访问授权等内容的梳理,可能漏掉的东西会比较多,漏掉的还是希望大家来补充。顺便说...

唐玄奘 ⋅ 2017/12/03 ⋅ 0

Spring Security Kerberos 1.0.0.RC2 发布

Spring Security Kerberos 1.0.0.RC2 发布,此版本主要改进如下: 增加支持 LdapContextSource 包的二次使用具有更好的管理属性 spring-security-kerberos-web 现在包含所有 Web 的相关属性(...

oschina ⋅ 2015/04/03 ⋅ 1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

IOS-UI UI初步代码布局添加事件

ISO开发界面,UI是必须学习的一部分,其实很早之前想学来了,一直没有沉下心来学习。看到IOS的代码风格和布局就别扭的不行,跟java代码和android布局比较显得不是那么方便,所以一直到现在。...

京一 ⋅ 28分钟前 ⋅ 0

浅谈OpenDaylight的二次开发

OpenDaylight作为一款开源SDN网络控制器,依托于强大的社区支持以及功能特性,成为了目前主流的SDN网络控制器开发平台。在比较稳定的OpenDaylight Helium版本中,已经为开发者提供了大量的网...

wangxuwei ⋅ 37分钟前 ⋅ 0

API 开发中可选择传递 token 接口遇到的一个坑

在做 API 开发时,不可避免会涉及到登录验证,我使用的是jwt-auth 在登录中会经常遇到一个token过期的问题,在config/jwt.php默认设置中,这个过期时间是一个小时,不过为了安全也可以设置更...

等月人 ⋅ 38分钟前 ⋅ 0

Java NIO之文件处理

程序要操作本地操作系统的一个文件,可以分为以下三个部分: 对文件位置的操作 对文件的操作 对文件内容的操作 其中,对文件内容的操作在 Java NIO之Channel 中已经有了介绍,通过FileChann...

士别三日 ⋅ 43分钟前 ⋅ 0

Maven的pom.xml配置文件详解

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.......

小海bug ⋅ 57分钟前 ⋅ 0

解决httpclient超时设置不生效的问题

最近公司有项目需要通过http调用第三方服务,且第三方服务偶有超时,故需要设置一定的超时时间防止不响应的情况出现。 初始设置如下: [java] view plain copy //超时设置 RequestConfig re...

Mr_Tea伯奕 ⋅ 今天 ⋅ 0

过滤器Filter和拦截器HandlerInterceptor

过滤器 依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要...

hutaishi ⋅ 今天 ⋅ 0

Redis入门详解(转)

Redis入门详解 Redis简介 Redis安装 Redis配置 Redis数据类型 Redis功能 持久化 主从复制 事务支持 发布订阅 管道 虚拟内存 Redis性能 Redis部署 Redis应用场景 Redis总结 Redis简介: Redi...

xiaoyaoyoufang ⋅ 今天 ⋅ 0

说说javascript中的那些专业名词

DOM(Document Object Model) 文档对象模型 BOM(Browser Object Model) 浏览器对象模型 ECMA(European Computer Manufacturer's Association) 欧洲计算机制造商协会 W3C(World Wide Web Conso......

hang1989 ⋅ 今天 ⋅ 0

Bootstrap Wizard 多步表单控件

废话 有一块需求是 有多步表单 点击下一步时触发验证一个范围内的表单,点击上一步或取消,清空表单并返回第一步,点击最后一步提交整个表单的 就找到了这个插件,本来自己写了一个原生的 fo...

无极之岚 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部