使用 DotNetNuke 作为用户存储的 SharePoint 基于表单的身份验证






4.90/5 (12投票s)
将 DotNetNuke 用户存储和管理用于使用基于表单的身份验证的 SharePoint Web 应用程序。
引言
在本文中,我将解释如何为使用基于表单的身份验证的 SharePoint Web 应用程序使用 DotNetNuke 用户存储和管理。
您可能知道,SharePoint 具有使用基于表单的身份验证的能力。如果您希望将 SharePoint 站点不仅公开给内部用户,还公开给 Internet 用户(例如合作伙伴、自行注册用户或仅仅是想要渗透您内网的黑客),这是一项非常重要的功能。
我假设您是一位 SharePoint 开发人员或管理员,被要求创建一个需要用户注册的某种外部 SharePoint 门户。您已经错过了最后期限,或者您只是太懒得从头开始编写用户管理系统(像我一样)。
DotNetNuke 不需要高级知识,但您至少应该知道它是什么。不,它不是一种能量饮料。它是一个免费的开源框架,非常适合创建企业 Web 应用程序。有关更多信息,请访问 www.dotnetnuke.com。
以下是基本步骤,或者换句话说,本文的各个部分
- 安装 DotNetNuke(如果您还没有安装)
- 修改 DotNetNuke 数据库以使 SQLRoleProvier 工作
- 创建将使用基于表单的身份验证的扩展 SharePoint Web 应用程序
- 修改 SharePoint 的web.config 文件
- 将 SharePoint 设置为使用基于表单的身份验证
- 为 DotNetUsers 设置访问 SharePoint 站点的权限
- 在 DotNetNuke 中注册并登录 SharePoint
安装 DotNetNuke
如果您还没有安装 DotNetNuke,请从此处的 这里 下载一个副本并进行安装(您需要注册)。即使 DotNetNuke 可能不是您的专长,安装难度也不会比 SharePoint 安装更难。以下是基本步骤
- 为将来的 DNN 站点创建一个新的 DNS 或 hosts 文件条目。我称之为:dnn.zeppelinsoft.com。
- 下载DotNetNuke_x_y_z_Source.zip。解压缩它,并设置一个 IIS 站点指向…/Website 文件夹。
- 确保您使用 ASP.NET 2.0 版本,并且 Network Services 用户有权限修改该文件夹。
- 如果您不想使用 SQL Express,请为将来的 DotNetNuke 站点创建一个空数据库。
- 在浏览器中加载您的站点,然后按照向导进行操作。选择典型,并将其配置为使用您新创建的数据库。设置数据库类型和连接是最重要的一步。
- 接下来,系统会要求您为两个用户设置密码和电子邮件:host 和 admin。您将在 SharePoint 中稍后使用这些用户作为站点集合管理员。

修改 DotNetNuke 数据库以使 SqlRoleProvider 工作
为了使用 DotNetNuke 作为用户存储,我们需要在 SharePoint 中设置两个提供程序
- Membership Provider:负责验证用户凭据、更改密码等。作为 Membership Provider,我们将使用SqlMembershipProvider(随 ASP.NET 2.0 提供)。DotNetNuke 为其提供本地支持。我们只需复制一些web.config 条目,就完成了。我稍后会在本文中向您展示。
- Role Provider:负责角色管理、验证用户角色等。在基于表单的身份验证中,角色类似于 Active Directory 中的用户组。DotNetNuke 不为SqlRoleProvider(随 ASP.NET 2.0 提供)提供本地支持,但它会创建该提供程序使用的所有存储过程。问题在于它不会使用其本地角色管理表中的数据填充SqlRoleProvider使用的表。这个问题有两种解决方案
- 在 SharePoint 中使用SqlRoleProvider,并修改其相应的 SQL 存储过程,以便使用其本地角色管理表。
- 创建一个新的角色提供程序,该提供程序将直接使用 DotNetNuke 的本地角色表。
我将在这里采用第一种方法。我们只需要修改以下 SQL 存储过程
- aspnet_Roles_GetAllRoles
- aspnet_Roles_RoleExists
- aspnet_UsersInRoles_FindUsersInRole
- aspnet_UsersInRoles_GetRolesForUser
- aspnet_UsersInRoles_GetUsersInRoles
- aspnet_UsersInRoles_IsUserInRole
我在这里做两个假设
- DotNetNuke 表没有表前缀。您在 DotNetNuke 安装过程中会被询问表前缀。如果您选择了前缀,那么您将不得不修改我的 SQL 脚本中的所有表引用以包含该前缀。
- DotNetNuke 安装中没有子门户(当然是为了简单起见)。这意味着我只使用根门户(PortalID = 0)来获取用户和角色的定义。
以下是完成此操作的 SQL 序列(针对 DotNetNuke 数据库执行)
/****** Object:  StoredProcedure [dbo].[aspnet_Roles_GetAllRoles]   ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_Roles_GetAllRoles] (
    @ApplicationName           nvarchar(256))
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN
    select RoleName from dbo.roles
    where 
    PortalID = 0
END
GO
/****** Object:  StoredProcedure [dbo].[aspnet_Roles_RoleExists]   ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_Roles_RoleExists]
    @ApplicationName  nvarchar(256),
    @RoleName         nvarchar(256)
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN(0)
    
    IF (EXISTS (SELECT RoleName FROM dbo.Roles WHERE LOWER(@RoleName) = lower(RoleName) 
    AND Portalid = 0 ))
        RETURN(1)
    ELSE
        RETURN(0)
END
GO
/****** Object:  StoredProcedure [dbo].[aspnet_UsersInRoles_FindUsersInRole] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_UsersInRoles_FindUsersInRole]
    @ApplicationName  nvarchar(256),
    @RoleName         nvarchar(256),
    @UserNameToMatch  nvarchar(256)
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN(1)
     DECLARE @RoleId int
     SELECT  @RoleId = NULL
     SELECT  @RoleId = RoleId
     FROM    dbo.Roles
     WHERE   
     RoleName  = @RoleName
     and
     PortalID = 0
     IF (@RoleId IS NULL)
         RETURN(1)
    SELECT u.UserName
    FROM   
    dbo.Users u, 
    dbo.UserRoles ur,
    dbo.Roles r
    WHERE  
    u.UserId = ur.UserId AND @RoleId = ur.RoleId 
    AND
    ur.RoleID = r.RoleID 
    AND
    r.PortalID = 0
    AND 
    u.Username LIKE LOWER(@UserNameToMatch)
    ORDER BY u.UserName
    RETURN(0)
END
GO
/****** Object:  StoredProcedure [dbo].[aspnet_UsersInRoles_GetRolesForUser] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_UsersInRoles_GetRolesForUser]
    @ApplicationName  nvarchar(256),
    @UserName         nvarchar(256)
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN(1)
    DECLARE @UserId uniqueidentifier
    SELECT  @UserId = NULL
    SELECT  @UserId = UserId
    FROM    dbo.aspnet_Users
    WHERE   LoweredUserName = LOWER(@UserName) AND ApplicationId = @ApplicationId
    IF (@UserId IS NULL)
        RETURN(1)
    select 
    a.RoleName
    from
    dbo.Roles a
    inner join dbo.UserRoles b on a.RoleID = b.RoleID
    inner join dbo.Users c on b.UserId = c.UserId
    where
    a.PortalID = 0 
    and
    c.Username = @UserName
    order by a.RoleName
    RETURN (0)
END
GO
/****** Object:  StoredProcedure [dbo].[aspnet_UsersInRoles_GetUsersInRoles] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_UsersInRoles_GetUsersInRoles]
    @ApplicationName  nvarchar(256),
    @RoleName         nvarchar(256)
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN(1)
    select a.UserName
    from
    dbo.Users a
    inner join 
    dbo.UserRoles b on a.UserId = b.UserId
    inner join 
    dbo.Roles c on b.RoleId = c.RoleId
    where
    c.RoleName = @RoleName
    and
    c.PortalId = 0
    RETURN(0)
END
GO
/****** Object:  StoredProcedure [dbo].[aspnet_UsersInRoles_IsUserInRole] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER  PROCEDURE [dbo].[aspnet_UsersInRoles_IsUserInRole]
    @ApplicationName  nvarchar(256),
    @UserName         nvarchar(256),
    @RoleName         nvarchar(256)
AS
BEGIN
    DECLARE @ApplicationId uniqueidentifier
    SELECT  @ApplicationId = NULL
    SELECT  @ApplicationId = ApplicationId FROM aspnet_Applications 
    WHERE LOWER(@ApplicationName) = LoweredApplicationName
    IF (@ApplicationId IS NULL)
        RETURN(2)
    if (exists(select * from dbo.Users a inner join dbo.UserRoles b on a.UserId = b.UserId
    inner join dbo.Roles c on b.RoleId = c.RoleId
    where c.RoleName = @RoleName and a.UserName = @UserName and c.PortalId = 0))
        return(1)
    else
        return(0)
END
呼,这不算太难。DotNetNuke 现在已准备好从 SharePoint 用作用户存储。
创建使用基于表单的身份验证的扩展 SharePoint Web 应用程序
考虑您已经有一个使用 Active Directory 进行身份验证的 SharePoint Web 应用程序的情况。我们将扩展此应用程序以使用 DotNetNuke 中的用户。为此,请按照以下步骤操作
- 为将来的 SharePoint 站点创建一个 DNS 或 hosts 文件条目。我给它起了一个富有创意的名字:sharepointdnn.zeppelinsoft.com。
- 登录到 Central Administration,然后转到 Application Management 页面。然后,单击 Create or Extend Web application。
- 选择Extend an existing Web application。在我的例子中,我正在扩展一个名为SharePointDNN的现有应用程序。
确保您执行以下操作
- 从 Web Application 下拉列表中选择正确的应用程序。
- 指定端口 80,并在 Host Header 条目中输入您在第一步中创建的名称(如果您愿意,可以创建新名称)。
- 选择 Internet 作为区域。

修改 SharePoint web.config 文件
在将我们的新扩展应用程序设置为使用与 DotNetNuke 的 FBA 之前,我们需要对 SharePoint FBA 应用程序以及 Central Administration 的web.config 文件进行几处更改。让我们从扩展应用程序(在我的例子中是SharePointDNN.zeppelinsoft.com)开始。在进行修改之前,我建议您进行备份。我们需要从 DotNetNukeweb.config 中窃取三个条目,并添加一个新条目,因此我建议在 Visual Studio 中打开两个web.config 文件,然后开始执行以下操作。
更改 SharePoint FBA 应用程序的web.config
- 复制 DotNetNukeweb.config 中的连接字符串条目。
- 复制 DotNetNuke 的<membership>部分,然后我们将进行一些创造性的更改,例如将提供程序的名称更改为DNNMembershipProvider,将连接字符串更改为DNNSqlServer。
- 添加<roleManager>条目。此条目在 DotNetNuke 中不存在,因此您必须手动添加它。将连接字符串设置为DNNSqlServer并将应用程序名称设置为DotNetNuke非常重要。
- 这非常重要:将<machineKey>原样从 DotNetNukeweb.config 复制到 SharePointweb.config。覆盖现有条目。(您有备份,对吗?)。<machineKey>用于哈希密码,并且对每个机器和应用程序都是特定的。除非您将DNNMembershipProvider中的passwordFormat属性设置为Clear,否则machineKey必须相同。
<connectionStrings>
  <add name="SiteSqlServer" 
    connectionString="Data Source=(local);Initial Catalog=DotNetNuke;
                      User ID=xxxxxx;Password=xxxxxx"
    providerName="System.Data.SqlClient" />
</connectionStrings>
将其粘贴到 SharePointweb.config 中。我将连接字符串的名称更改为DNNSqlServer,以便web.config 阅读器更容易知道它指向 DNN SQL Server。以下是实际粘贴到 SharePointweb.config 中的内容。
<!-- changed for FBA with DotNetNuke-->
<connectionStrings>
  <add name="DNNSqlServer" 
       connectionString="Data Source=(local);Initial Catalog=DotNetNuke;
                         User ID=xxxxxx;Password=xxxxxx" 
       providerName="System.Data.SqlClient" />
</connectionStrings>
DotNetNuke 中的初始 membership 条目如下所示
<membership defaultProvider="AspNetSqlMembershipProvider" 
            userIsOnlineTimeWindow="15">
   <providers>
     <clear />
     <add name="AspNetSqlMembershipProvider" 
        type="System.Web.Security.SqlMembershipProvider" 
        connectionStringName="SiteSqlServer" 
        enablePasswordRetrieval="true" 
        enablePasswordReset="true" 
        requiresQuestionAndAnswer="false" 
        minRequiredPasswordLength="7" 
        minRequiredNonalphanumericCharacters="0" 
        requiresUniqueEmail="false" 
        passwordFormat="Encrypted" 
        applicationName="DotNetNuke" 
        description="Stores and retrieves membership data from 
                     the local Microsoft SQL Server database" />
   </providers>
 </membership>
修改 SharePoint 中的 membership 条目
<!-- changed for FBA with DotNetNuke-->
<membership defaultProvider="DNNMembershipProvider" userIsOnlineTimeWindow="15">
   <providers>
     <clear />
     <add name="DNNMembershipProvider" 
        type="System.Web.Security.SqlMembershipProvider" 
        connectionStringName="DNNSqlServer" 
        enablePasswordRetrieval="true" 
        enablePasswordReset="true" 
        requiresQuestionAndAnswer="false" 
        minRequiredPasswordLength="7" 
        minRequiredNonalphanumericCharacters="0" 
        requiresUniqueEmail="false" 
        passwordFormat="Encrypted" 
        applicationName="DotNetNuke" 
        description="Stores and retrieves membership data from 
                     the local Microsoft SQL Server database" />
   </providers>
</membership>
<!-- changed for FBA with DotNetNuke-->
<roleManager enabled="true" defaultProvider="DNNRoleProvider">
    <providers>
        <add name=" DNNRoleProvider " 
             connectionStringName="DNNSqlServer" 
             applicationName="DotNetNuke" 
             type="System.Web.Security.SqlRoleProvider,System.Web,
                   Version=2.0.0.0,Culture=neutral,
                   PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
</roleManager>
更改 Central Administration 应用程序的 web.config
- 将与 SharePoint FBA 应用程序 1 和 2 相同的更改应用于此,即为 SQL 连接字符串和 Membership Provider 添加相同的条目。
- 添加相同的<roleManager>条目,但将其默认设置为AspNetWindowsTokenRoleProvider。这是因为我们只需要让 CA 知道DNNRoleProvider,但我们仍然希望为 Central Admin 使用 Windows 身份验证。这是条目。
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
    <providers>
        <add name="DNNRoleProvider" 
            connectionStringName="DNNSqlServer" 
            applicationName="DotNetNuke" 
            type="System.Web.Security.SqlRoleProvider,
                  System.Web,Version=2.0.0.0,Culture=neutral,
            PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
</roleManager>
将 SharePoint 设置为使用基于表单的身份验证
现在,我们已经在web.config 文件中放置了所有条目,我们需要在 Central Admin 中将 SharePoint 应用程序设置为使用 Forms 身份验证。步骤如下。
- 转到 Central Administration -> Application Management -> Authentication Providers(在 Application Security 部分下)。
- 将 Web Application 更改为我们正在处理的应用程序(在本例中为 SharePointDNN)。然后,单击 Internet zone。
- 将Authentication Type更改为:Forms。将Membership provider名称输入为:DNNMembershipProvider。将Role Manager输入为:DNNRoleProvider。为Enable Client Integration选择Yes。
- 现在,您应该在 Membership Provider Name 列中看到指定的DNNMembershipProvider。




为 DotNetNuke 用户设置访问 SharePoint 站点的权限
- 此时,我们有一个使用基于表单的身份验证的站点,但没有用户被设置为访问它。因此,转到 Central Administration -> Application Management -> Site Collection Administrators(在 SharePoint Site Management 下),并将host(DotNetNuke 中的超级管理员用户)添加为辅助站点集合管理员。
- 转到 Central Administration -> Application Management -> Policy for Web Applications(在 Application Security 下),并将 Registered Users(DotNetNuke 中的公共角色)添加到 SharePointDNN 的 Internet zone 作为读者。

在 DotNetNuke 中注册,然后登录 SharePoint
通过稍加努力,我们可以修改 SharePoint 登录页面,使其包含指向 DotNetNuke 中注册页面的链接。在 Visual Studio 中打开../12/TEMPLATE/LAYOUTS/login.aspx,并添加指向 DotNetNuke 中注册页面的链接。链接应如下所示:http://dnn.zeppelinsoft.com/?ctl=register。登录页面应如下所示。

再稍微努力一下,我们就可以在注册后将用户重定向回 SharePoint,方法是在 DotNetNuke 中创建一个包含重定向 JavaScript 代码的页面。要创建 DotNetNuke 页面,请以 host 身份登录,然后转到 Admin -> Pages -> Add New Page。让我们将其命名为SharePoint Redirect Page。然后,向页面添加一个 Text/HTML 模块。编辑它,并添加类似以下的代码。
<script language="JavaScript">
<!--
location.href = 'http://sharepointdnn.zeppelinsoft.com';
// -->
</script>
现在,加载 Membership Provider Settings 页面:转到 Admin -> User Accounts -> User Settings。在此页面上,将Redirect After Registration设置为我们刚刚创建的页面SharePoint Redirect Page。

现在,如果您尝试访问sharepointdnn.zeppelinsoft.com,您将看到一个登录页面,并可以选择通过 DotNetNuke 进行注册。注册后,您将被重定向回 SharePoint。
当然,这是可能的最简单场景之一。DotNetNuke 支持不同类型的用户注册:公共、已验证或私有。在本例中,它是公共的。如果您希望用户接收确认电子邮件,请将其设置为已验证。
结论
您可以使用 DotNetNuke 进行 SharePoint 用户管理。
好了,这只是对使用 DotNetNuke 和 SharePoint 进行身份验证和注册的用户管理所能做的事情的初步介绍。DotNetNuke 是一个成熟、非常健壮的系统,有许多热情的用户日夜开发组件。您可以从 DotNetNuke 中获得许多由他人已经完成的事情,例如用户管理。

