SharePoint 2010中默认的FBA登录页面非常简单,只提供了一个Asp.Net的Login控件,让用户输入用户名和密码。在大多数情况下,我们需要定制这个页面以满足一些安全需求,比如为登录页面加上验证码等等。

由于SharePoint 2010里的FBA已经变成了基于Claims认证的方式,因此在实现自定义的登录页面时就与MOSS 2007里的做法完全不同了。最显著的一点就是,像Steve Peschka说的,以前的FormsAuthentication类不会再被用到了。现在我们需要用SharePoint的STS来做认证和处理Claims。好在SharePoint提供了相应的借口,让这一切变得容易了许多。这这篇文章里,我将演示如何创建自定义登录页面,并保持默认的master page和样式。

由于要修改默认页面,我不知道这样的做法是否受Microsoft官方支持,如果你要用在你的项目中,风险自负。

创建自定义登录页面

如果我们留意一下会发现,默认的FBA登录页面是_forms/default.aspx。这样的设计有一个好处,就是如果我们修改了default.aspx,它不会影响别的Web app。下面我就在一个default.aspx页面上加了一个验证码功能。

<asp:login id="loginControl"      
    FailureText="<%$Resources:wss,login_pageFailureText%>"      
    runat="server" width="100%" OnLoggingIn="signInControl_LoggingIn"      
    OnAuthenticate="signInControl_Authenticate"> <layouttemplate>      
        <asp:label id="FailureText" class="ms-error" runat="server"/>      
        <table width="100%">      
        <tr>      
            <td nowrap="nowrap">      
                <SharePoint:EncodedLiteral runat="server"      
                    text="<%$Resources:wss,login_pageUserName%>"      
                    EncodeMethod='HtmlEncode'/>      
            </td>      
            <td width="100%">      
                <asp:textbox id="UserName"      
                    autocomplete="off"      
                    runat="server"      
                    class="ms-inputuserfield" width="99%" />      
            </td>      
        </tr>      
        <tr>      
            <td nowrap="nowrap">      
                <SharePoint:EncodedLiteral runat="server"      
                    text="<%$Resources:wss,login_pagePassword%>"      
                    EncodeMethod='HtmlEncode'/>      
            </td>      
            <td width="100%">      
                <asp:textbox id="password" TextMode="Password"      
                    autocomplete="off" runat="server"      
                    class="ms-inputuserfield" width="99%"/>      
            </td>      
        </tr>      
        <tr>        
            <td nowrap="nowrap">        
                <SharePoint:EncodedLiteral runat="server"        
                    text="Secure Code:" EncodeMethod='HtmlEncode'/>        
            </td>        
            <td width="100%">        
                <asp:textbox id="secureCode" autocomplete="off"        
                    runat="server" class="ms-inputuserfield" Width="85%" />        
                <SharePoint:EncodedLiteral ID="secureCodeLit"        
                    runat="server" Text="1234" EncodeMethod="HtmlEncode" />        
            </td>        
        </tr>
        <tr>      
            <td colspan="2" align="right">      
                <asp:button id="login" commandname="Login"      
                    text="<%$Resources:wss,login_pagetitle%>" runat="server" />      
            </td>      
        </tr>      
        <tr>      
            <td colspan="2">      
                <asp:checkbox id="RememberMe"      
                    text="<%$SPHtmlEncodedResources:wss,login_pageRememberMe%>"      
                    runat="server" />      
            </td>      
        </tr>      
        </table>      
    </layouttemplate>      
</asp:login>

我的想法是,当用户登录的时候,只有输入了正确的用户名密码和验证码,这里是1234,之后才能成功登录。页面运行的效果如下:

当然,此时验证码还没有作用,我们必须写一些代码来实现验证的功能。

创建Code Behind类实现验证和登录功能

接下来是为default.aspx实现一个类来实现验证和登录功能。在项目中添加一个类,可以命名为FormsSignInPage。接着是添加一些引用,首先是Microsoft.SharePoint.dll。由于我们要处理Claims,System.IdentityModel.dll和Microsoft.IdentityModel.dll也是必须的。另外,SharePoint有一个自己的处理Claims的Module,Microsoft.SharePoint.IdentityModel.dll。添加对它的引用时,需要定位到它所在的目录。引用添加完,看起来像下面这样。

我们的类,FormsSignInPage,当然可以从Asp.Net的Page类派生,但是如果我们看一下默认的登录页面,它是派生自IdentityModelSignInPageBase。这个类在Microsoft.SharePoint.IdentityModel.Pages名字空间下,它提供了一些属性和方法,在处理登录时很方便。所以,我决定我的FormsSignInPage也从这个类派生。

当用户点击页面上的登录按钮时,有两个Login控件的事件需要处理,一个是LoggingIn,在这个事件中,我们可以处理验证码。另一个是Authenticate,在这个事件中可以实现真正的登录。

protected void signInControl_LoggingIn(objectsender, LoginCancelEventArgs e)     
{     
    LoginControl login = sender asLoginControl;     
    login.UserName = login.UserName.Trim();     
    if(string.IsNullOrEmpty(login.UserName))     
    {     
        ClaimsFormsPageMessage.Text = "The server could not sign you in. The user name cannot be empty.";     
        e.Cancel = true;     
    }     
    if(string.IsNullOrEmpty(secureCode.Text) ||     
        !string.Equals(secureCode.Text.ToLower(), secureCodeLit.Text.ToLower()))     
    {     
        ClaimsFormsPageMessage.Text = "The server could not sign you in. Please input correct secure code.";     
        e.Cancel = true;     
    }     
}

private void EstablishSessionWithToken(SecurityToken securityToken)     
{     
    if (null == securityToken)     
    {     
        throw new ArgumentNullException("securityToken");     
    }     
    SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;     
    if (null == fam)     
    {     
        throw new ArgumentException(null, "FederationAuthenticationModule");     
    }

fam.SetPrincipalAndWriteSessionToken(securityToken);     
}

protected void signInControl_Authenticate(object sender, AuthenticateEventArgs e)     
{     
    SecurityToken token = null;     
    LoginControl formsLoginControl = sender as LoginControl;

if (null != (token = GetSecurityToken(formsLoginControl)))     
    {     
        EstablishSessionWithToken(token);     
        e.Authenticated = true;     
        base.RedirectToSuccessUrl();     
    }     
}

private SPIisSettings IisSettings     
{     
    get      
    {     
                
        SPWebApplication webApp = SPWebApplication.Lookup(new Uri(SPContext.Current.Web.Url));

SPIisSettings settings = webApp.IisSettings[SPUrlZone.Default];   
        return settings;   
    }   
}

private SecurityToken GetSecurityToken(LoginControl formsLoginControl)   
{   
    SecurityToken token = null;   
    SPIisSettings iisSettings = IisSettings;   
    Uri appliesTo = base.AppliesTo;

if (string.IsNullOrEmpty(formsLoginControl.UserName) ||   
        string.IsNullOrEmpty(formsLoginControl.Password))   
        return null;

SPFormsAuthenticationProvider authProvider = iisSettings.FormsClaimsAuthenticationProvider;     
    token = SPSecurityContext.SecurityTokenForFormsAuthentication(     
        appliesTo,     
        authProvider.MembershipProvider,     
        authProvider.RoleProvider,     
        formsLoginControl.UserName,     
        formsLoginControl.Password);

return token;   
}

代码的核心部分是执行登录的部分。SharePoint提供了SecurityTokenForFormsAuthentication专门供开发者处理Forms验证。我使用了SPIisSettings来取得当前Web App所使用的membership provider和roleship provider。

SPFormsAuthenticationProvider authProvider = iisSettings.FormsClaimsAuthenticationProvider;     
token = SPSecurityContext.SecurityTokenForFormsAuthentication(     
    appliesTo,     
    authProvider.MembershipProvider,     
    authProvider.RoleProvider,     
    formsLoginControl.UserName,     
    formsLoginControl.Password);

关联Default.aspx和FormsSignInPage

这部分比较简单,只要修改<%@ Page %>使它继承我们的FormsSignInPage就好了。

<%@PageLanguage="C#"AutoEventWireup="true"      
   Inherits="Morpheus.Demo.Pages.FormsSignInPage,FormsSignInPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=72d2bbe72853b8eb"      
   MasterPageFile="~/_layouts/simple.master"%>

然后我们就可以将我们的Assembly部署到GAC中,同时将default.aspx拷贝到_forms目录里。当执行登录时,如果用户没有输入正确的验证码,下面的错误会显示出来。

为SharePoint 2010中的FBA创建自定义登录页面的更多相关文章

  1. SharePoint 2013中以其他用户身份登录的WebPart(免费下载)

    在SharePoint 2013中微软并没有提供在SharePoint 2010中以其他用户身份登录的菜单,这对一般用户影响不大,但对于系统管理员或测试人员或特定人员(如在OA系统中的文员或秘书,常常 ...

  2. 在SharePoint 2010中创建网站的权限级别

    转:http://www.360sps.com/Item/CreatePermissionLevels.aspx 权限级别是SharePoint 2010新增加的功能,使我们对权限的设置又提高了一个层 ...

  3. SharePoint 2010 中创建超链接到Pop-Up对话框

    SharePoint 2010 中创建超链接到Pop-Up对话框         SharePoint 2010 推出了新式的带有阴影的弹出对话框,你感觉怎么样?我感觉倒是挺酷的.这样少打开了一个页面 ...

  4. 在Sharepoint 2010中启用Session功能的说明文档

    在Sharepoint 2010中启用Session功能的说明文档 开发环境:Windows 7系统,SharePoint Server 2010,Visual Studio 2010 按以下步骤进行 ...

  5. 在 SharePoint 2010 中访问数据

    转:http://blog.banysky.net/?p=81001 数据访问的关键方法有哪些? | 使用查询类 | 使用 SPQuery | 使用 SPSiteDataQuery | 使用 LINQ ...

  6. VSTO学习笔记(四)从SharePoint 2010中下载文件

    原文:VSTO学习笔记(四)从SharePoint 2010中下载文件 上一次我们开发了一个简单的64位COM加载项,虽然功能很简单,但是包括了开发一个64位COM加载项的大部分过程.本次我们来给CO ...

  7. 关于SharePoint 2010中不能使用AjaxControlToolkit的解决办法

    因为项目中有一个需求需要使用calendar控件,而且样式要和Reporting Service中的尽量一致,搜索了很久发现还是微软的AjaxControlToolkit提供的CalendarExte ...

  8. SharePoint 2010中重置windows 活动目录(AD)域用户密码的WebPart(免费下载)

    由于SharePoint 2013推出不久,并非所有的企业都会升级到SharePoint 2013的,毕竟升级不是打打补丁这么简单,更多的企业还是使用Sharepoint 2010版本的,因此本人自行 ...

  9. 在SharePoint 2010中部署RBS (转)

    一.RBS(Remote BLOB Storage)简单介绍 在SharePoint的大部分企业应用案例中,SharePoint都是要承担着非常繁重的文件管理工作,这些文件类型包含了Word文档,Ex ...

随机推荐

  1. 一个简单java爬虫爬取网页中邮箱并保存

    此代码为一十分简单网络爬虫,仅供娱乐之用. java代码如下: package tool; import java.io.BufferedReader; import java.io.File; im ...

  2. Linux系统中“动态库”和“静态库”那点事儿

    摘自http://blog.chinaunix.net/uid-23069658-id-3142046.html 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在 ...

  3. [置顶] Firefox OS 学习——简单了解知识

    什么是Firefox OS ? Firefox OS 是一个为网页设计而生的能编译和独立的手机网页操作系统,我们相信在接下来的时代,网页应用将充满整个新兴操作设备,这也为当前许多网页开发者不需要太多的 ...

  4. gateone安装(web版本ssh)

    前言: 好久都没来写博客,最近忙啥去了呢? 一是忙于saltstack的二次开发,二是云计算的学习研究中,所以就一直没写东西,今天给大家介绍个工具. 好了,开始正文! 1.首先来说一下为什么要web ...

  5. Java基础笔记-String类

    String 类(被final修饰) 字符串是一种特殊的对象,一旦字符串被初始化就不可以被改变了.(内容不变) 例如: String  s = “abc”; String  s1 = new Stri ...

  6. 引言:Canvas绘图API快速入门

    引言:Canvas绘图API快速入门 在接触HTML5的初学者包括我都在很多地方见到非常炫的一些页面,甚至好多学习HTML5的开发者都是冲着Web端的页游去的,那么HTML5那么绚丽的页面效果以及游戏 ...

  7. SQL Server 创建作业系列问题

    一.从IClassFactory为CLSID为{AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2}的COM组件创建实例失败. 尊重原著作:本文转载自http://www.hao ...

  8. python学习笔记:python数字

    一.数字类型分类 数字提供了标量存储和直接访问,它是不可更改类型,也就是说变更数字的值会产生新的对象.python的对象模型与常规对象模型有些不同,对数字对象的更新,实际上是生成了一个新的数值对象,并 ...

  9. Android 自定义EditText实现粘贴,复制,剪切的监听

    package com.dwtedx.qq.view; import android.annotation.SuppressLint; import android.content.Context; ...

  10. 重新理解一遍UpdatePanel

    楼主只是想每天写点东西这样帮助自己的一个累积吧. 说明:楼主现在已经清楚了AJAX是怎么回事了,现在由于工作原因又摆弄起了UpdatePanel所以从AJAX的角度来分析一下UpdatePanel的使 ...