前几天研究了,感触很深,所以在此写下和大家分享一下。
单点登录(Single Sign On),简称为 SSO。
定义:
SSO的定义是在多个模块中,用户只需要登录一次就可以访问所有相互信任的模块。
实现机制:
有2个应用系统,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份效验,如果通过效验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候就会将这个ticket带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行效验,检查ticket的合法性。如果通过效验,用户就可以在不用再次登录的情况下访问应用系统2了。
比如:你去游玩欢乐谷,只需要在大门口买一张ticket(登录一次)后就可以游玩里面所有的项目(应用系统)了,而避免了每次玩一个项目(应用系统)时再从书包里拿出钱,再买对应那个项目的ticket(每次登录)的问题了。
示意图:
程序构造:
具体实现:
登陆客户界面WebApp1/SSOLogin后,页面会调用SSOServer里边的SSOContext.aspx页面,获取由SSOContext.aspx页面所生成的用户信息(XML信息与JavaScript信息),利用此信息判断用户是否在SSOServer内部登陆,如果登陆了,则会给用户发放一个本应用程序的票据;如果没有则会跳转到SSOServer内的SSOLogin.aspx页面让用户登陆,登陆成功会在SSOServer上面创建用户Session状态对象,然后会自动返回到WebApp1应用程序,再生成用户信息(根据SSOServer内部的Session状态对象生成对应的XML格式的用户信息)和JavaScript脚本。所以一旦登录WebApp1后也就能直接查看WebApp2的内容了。
SSO\SSOContext.aspx代码:
//构建用户信息XML
StringBuilder userInfo = new StringBuilder();
userInfo.Append("<userinfo>");
if (Session["USER_IsLogin"] != null && (bool)Session["USER_IsLogin"] == true && Session["USER_LoginName"] != null)
{
string LoginName = Session["USER_LoginName"].ToString();
userInfo.Append("<username>").Append(LoginName).Append("</username>");
userInfo.Append("<islogin>true</islogin>");
}
else
{
userInfo.Append("<username></username>");
userInfo.Append("<islogin>false</islogin>");
}
userInfo.Append("<synchdate>").Append(DateTime.Now.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss")).Append("</synchdate>");
userInfo.Append("</userinfo>");
//构建调用JavaScript函数
StringBuilder sb = new StringBuilder();
sb.Append("function SSOContext(_signInUrl, _signOutUrl, _userInfo) { ").Append("\r\n");
sb.Append("this.signInUrl=_signInUrl;").Append("\r\n");
sb.Append("this.signOutUrl=_signOutUrl;").Append("\r\n");
sb.Append("this.userInfo=_userInfo;").Append("\r\n");
sb.Append("}").Append("\r\n");
sb.Append("var ssoContext=");
sb.Append("new SSOContext(");
sb.Append("'").Append(commTools.GetSiteUrl() + "/SSOLogin.aspx").Append("', ");
sb.Append("'").Append(commTools.GetSiteUrl() + "/SSOLogout.aspx").Append("', ");
WebApp1\SSOLogin代码:
string appKey = ConfigurationManager.AppSettings["moduleKey"].ToString();
string userInfo = Request.Params["sso_userinfo"];
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(userInfo);
if (xmlDoc.SelectSingleNode("/userinfo/islogin").InnerText == "true")
{
FormsAuthentication.RedirectFromLoginPage(xmlDoc.SelectSingleNode("/userinfo/username").InnerText, false);
}
else
{
string returnUrl = this.GetHostUrl() + FormsAuthentication.LoginUrl;
string loginUrl = Request.Params["sso_signinurl"].ToString();
Response.Redirect(loginUrl + "?ReturnUrl=" + HttpUtility.UrlEncode(returnUrl));
}
PS:早就在博客园上注册账号了,但是一直没有写博客,以后会经常写写,希望大家能提提建议,也希望和大家深讨关于.net的问题。
原创:http://www.cnblogs.com/liveviva7/archive/2010/11/08/1872053.html