最近接到了一个任务。实现公司内部办公平台(基于SharePoint 2007,Windows集成身份认证)和Mantis Bug管理系统(基于php和Mysql数据库,开源,Form认证)的单点登陆。本来,Mantis是一个开源的项目,修改一下它的认证方式应该就可以了,网上也有人介绍过关于在php中使用LDAP的经验,可惜啊,本人不懂php,只会ASP.NET,所以想到的解决方法是利用MOSS的SSO,首先在这一部分我来配置使用MOSS的SSO,在后面的一部分中我将向大家介绍怎么取得SSO里存放的Mantis用户名和密码并模拟Post提交。
首先启动Microsoft Single Sign-on Service服务,该服务默认状态未启动。如图:
右键单击服务—属性,点击上方选项卡中的登录,选择“此账户”,输入管理员的用户名和密码,如图:
再点击选项卡中的常规,将启动类型修改为“自动”,并启动该服务,可能会提示你新账户必须在重启计算机后才有效,重启。如图:
接下来我们要配置MOSS的SSO。进入管理中心---操作,点击安全性配置中下方的“管理单一登录的设置”,在服务器设置中点击“管理服务器设置”,依次在“单一登录管理员账户”和“企业应用程序定义管理员账户”中输入我们的管理员账户和密码,其他可用默认设置,如图:
确定之后,返回操作界面,在企业应用程序定义设置中,点击“管理企业应用程序定义的设置”,点击“新建项目”,在显示名称和应用程序名称中填入合适的名字,这个应用程序名字在第二部分用程序读SSO中存放的用户名和密码时会用到,在这儿我填的是mantis,再填入联系人电子邮件地址,在账户类型中,我们选择个人,可以详细看一下左侧的介绍。点击确定返回。再次进入操作--管理单一登录界面下,在企业应用程序定义设置中,点击“管理企业应用程序定义的帐户信息”,选择相应的企业应用程序,在用户账户名称中,输入对应的域账户,点击设置,在用户名和密码中,分别登录第三方系统的用户名和密码后,点击确定,可继续设置域账户与第三方系统用户名密码的对应,或者点击已完成。
这样,关于单点登陆的创建配置工作就已经完成了,然后需要取得存放在SSO数据库中的用户名和密码,并使用它们进行POST提交登陆。思路是这样的,在MOSS中创建一个aspx页面,重写这个页面的Page_Load事件,也许你会说,MOSS页面里不能使用服务器端代码,关于这方面的介绍,请参考我的另两个帖子:为MOSS页面添加后台代码的两种方式(一) 为MOSS页面添加后台代码的两种方式(二),
在Page_Load事件中,只有几行代码,根据当前登陆域帐户去取第三方系统Form认证的用户名和密码(在我这里是Mantis),并赋值给这个aspx页面的用户名和密码的输入框中,这两个是隐藏的,然后再在windows的onload事件中,执行aspx页面上Form的提交操作。以前看过有人做的OWA访问邮箱的webpart其实也是这种思路,大家都知道,MOSS自带的那个OWA webpart基本没有使用价值。
那我们就一步步来。首先创建一个aspx页面,这个页面完成模拟Post提交的工作,用Designer打开MOSS站点,测试的时候,我直接在站点的根路径下创建的这个页面,需要引用三个命名空间,在aspx页面顶部我们这样来写:
<%@ Page Language="c#" CodePage="936"%>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.Portal" %>
<%@ Import Namespace="Microsoft.SharePoint.Portal.SingleSignon" %>
第一行的CodePage=”936”是一个编码格式的问题,我在Post到mantis时需要,对你并不一定是必须的。引用之后,我们就可以写Page_Load事件了,这段代码我是参考网上一哥们写的,可以拿去直接使用:
<script type="text/c#" runat="server">
protected void Page_Load(object sender, EventArgs e)
{
IntPtr pUserName = IntPtr.Zero;
IntPtr pPassword = IntPtr.Zero;
ISsoProvider isso = SsoProviderFactory.GetSsoProvider();
SsoCredentials myCreds = isso.GetCredentials("mantis");//第一部分提到的应用程序名字,我这是mantis
pUserName = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(myCreds.UserName);
String userName = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(pUserName);
pPassword = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(myCreds.Password);
String passWord = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(pPassword);
this.username.Value = userName;
this.password.Value = passWord;
}
</script>
其中,username和password是我们页面上的两个服务器端控件,下面就是我们构建的模拟提交的Form:
<form action="要Post的地址" method="POST" name="登陆页面Form名字 " autocomplete="off">
<input type="hidden" name="return" value="Post成功后的地址">
<input name="username" runat="server" id="username" type="hidden">
<input name="password" runat="server" id="password" type="hidden">
</form>
当然,你可能不知道一个第三方系统Post到哪里去,我们需要借助一个IE插件HttpWatch来分析一下,点击插件的Record,当我们再点登陆的时候,就会看到我们需要的post地址,如图:
第一行就是Post的地址,第二行是在登陆成功后转至的地址,我们需要的就是这两个。
然后我们再查看一下页面的源文件,找到Form的名字及输入用户名和密码的两个文本框,在Mantis里是login_form 、username和password,就用这三个名字来分别命名我们页面上的控件。
到这里,我们已经完成了根据当前登陆的域帐户取得Mantis里的用户名和密码,并赋值到页面中,现在需要做的只是在windows.onload时,将页面提交出去。
在Form的下面,我们这样来写:
<script type="text/javascript">
window.οnlοad=function (){document.login_form.submit();};
</script>
这样完成之后,当登陆的域用户打开上面这个页面后,页面会自动找到与该用户对应的Mantis用户名和密码,并自动Post提交登陆,从而跳过Mantis的login界面。这样,我们就利用MOSS的SSO实现了单点登录Mantis。