choral's blog

Tech-on-Office

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::


SharePoint Portal Server 2003提供了一个看上去很酷的功能:单点登陆(Single Sign On)
SPS可以为网站用户记录其在其他应用系统中的登陆凭据,而我们的程序(WebPart)可以通过获取并利用这些凭据代替用户登陆第三方应用系统,并输出所需要展示的数据。
其工作原理大致如下:
1、用户访问网站上的单点登陆WebPart
2、WebPart通过Single Sign On的对象模型从SSO数据库中查找当前用户的凭据
3、如果没有此凭据,则将用户导引至输入凭据的页面
4、如果有此凭据,则通过此凭据登陆第三方应用系统,获取相关业务数据

有关Single Sign On的管理和使用,可以参考kaneboyWebcast,并且有相关的源代码下载。

这篇文章中主要介绍的内容是上述工作原理的第三步:用户输入凭据的页面。
如果使用默认的输入页面(用如下代码获得URL):

SingleSignonLocator.GetCredentialEntryUrl("FormSSO")


用户将在这样的页面中输入登陆凭据:


这个页面是一个典型的sharepoint的_layouts目录.NET应用页面。
就个人而言,我很喜欢这样的页面风格,但是我们还是会面对修改这个页面的需求,即我们需要用自己开发的页面引导用户输入其应用凭据。

那么,如何自己编写实现此功能的页面呢?接下来是一个实例:

1、打开vs2003,在http://localhost/_layouts/SSOSample下创建一个ASP.NET的web应用程序。(当然你要记得把“Localhost”换成你的SharePoint站点地址)
2、创建一个新的用户控件
3、在用户控件中拖入几个必需的web控件:

如上图,两个TextBox,一个按钮,以及一个显示错误信息的Label。
同时,为了向那些已经拥有凭据的用户隐藏输入框,我们把前3个控件包含在一个Panel中,并另这个Panel默认隐藏。
4、编写“保存”按钮的响应函数:

        private void btnSave_Click(object sender, System.EventArgs e)
        
{
            
if (this.tbUserName.Text == null || this.tbUserName.Text =="")
            
{
                
this.lbOutput.Text = "请输入用户名";
                
return;
            }

            
if (this.tbPassword.Text == null || this.tbPassword.Text =="")
            
{
                
this.lbOutput.Text = "请输入登陆密码";
                
return;
            }

            
string[]     rgSetCredentialData = new string[2];
            rgSetCredentialData[
0= this.tbUserName.Text;
            rgSetCredentialData[
1= this.tbPassword.Text;
            
try
            
{
                Credentials.SetCredentials(
1"SSOTEST", rgSetCredentialData);
            }

            
catch(SingleSignonException esso)
            
{
                
this.lbOutput.Text = esso.Message + "<br>" + esso.StackTrace;
            }

            
this.Page.Response.Redirect(this.Page.Request.Url.ToString());
        }

为了演示,我在Page_Load函数中加入如下代码,使得已经填写SSO凭据的用户可以浏览到自己凭据内容:
        private void Page_Load(object sender, System.EventArgs e)
        
{
            
// 在此处放置用户代码以初始化页面
            try
            
{
                String[] asCredData 
= null;

                Credentials.GetCredentials(
1"SSOTEST"ref asCredData);

                String sUsername 
= asCredData[0];
                String sPassword 
= asCredData[1];

                
this.lbOutput.Text = sUsername + "<br>" + sPassword;

            }

            
catch (SingleSignonException ex)
            
{
                
if (SSOReturnCodes.SSO_E_CREDS_NOT_FOUND == ex.LastErrorCode)
                
{
                    
if (!this.IsPostBack)
                    
{
                        
this.tbPassword.Text = "";
                        
this.tbUserName.Text = "";
                        
this.pnlSSOPart.Visible = true;
                    }

                    
else
                    
{
                        
this.lbOutput.Text = "请重新填写您的帐户信息";
                    }

                }

            }


        }

5、一切并没有到此结束,如果直接编译运行,我们在点击按钮的时候会收到这样的出错信息:

at Microsoft.SharePoint.Portal.SingleSignon.SSOCanaryChecker.b() at Microsoft.SharePoint.Portal.SingleSignon.SSOCanaryChecker.b() at Microsoft.SharePoint.Portal.SingleSignon.Credentials.SetCredentials(UInt32 ui32Flags, String strApplicationName, Object[] Args)

这是因为页面安全性的问题。我们需要在页面中引入SharePoint的FormDigest控件和SSOFormDigest控件:
即在用户控件的ascx文件中加入:
<%@ Register TagPrefix="cc2" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="cc1" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<cc2:formdigest id="FormDigest1" runat="server"></cc2:formdigest>
<cc1:ssoformdigest id="SSOFormDigest1" runat="server"></cc1:ssoformdigest>
当然我们也可以在工具栏中直接添加这两个控件,通过对用户控件进行拖放操作达到同样的目的。

这个解决办法,尤其是引入SSOFormDigest控件,我是从以下文章找到的:
http://geekswithblogs.net/tariq/archive/2004/09/10/10961.aspx
当然,我是从GOOGLE中搜索得到这一文章的。
插句题外话,我非常赞同熊明峰同志的观点:在使用GOOGLE中一定要使用恰当的搜索关键词,才能获得最有效率的搜索结果,所以我希望大家都能分享自己搜索到可用信息时使用的关键词,来提高自己的搜索技能。也许并不遥远的以后,选择关键词的能力将成为人类重要技能之一。
我使用的关键词:sharepoint SetCredentials


6、我们的用户SSO凭据存储功能基本就完成了:
一个没有凭据的用户登陆此页面时,需要填写新的用户凭据:

一旦保存成功,用户再次登陆的时候,SPS就能直接返回其对应的用户凭据内容:



好。接下来你就可以躲到写字楼的安全通道抽支烟,把剩下的工作丢给美工了。
至少我是这么干的。
posted on 2006-03-01 03:23  choral  阅读(7843)  评论(2编辑  收藏  举报