关于sso 网页跳转 的代码.
在我的上篇博客中,我介绍了网页跳转的sso 方案,http://www.cnblogs.com/jake1/archive/2013/04/28/sso_page.html
接下来,我把部分实现的代码也共享出来,供大家参考.
首先,单点登录中心,我们以前做的项目,就把portal网站,作为单点登录的中心.
单点登录,中心,通过实现Ihttphandle获取的.
View Code
1 public class SsoHander : IHttpHandler 2 { 3 /// <summary> 4 /// 您将需要在您网站的 web.config 文件中配置此处理程序, 5 /// 并向 IIS 注册此处理程序,然后才能进行使用。有关详细信息, 6 /// 请参见下面的链接: http://go.microsoft.com/?linkid=8101007 7 /// </summary> 8 #region IHttpHandler Members 9 10 public bool IsReusable 11 { 12 // 如果无法为其他请求重用托管处理程序,则返回 false。 13 // 如果按请求保留某些状态信息,则通常这将为 false。 14 get { return false; } 15 } 16 17 18 19 public void ProcessRequest(HttpContext context) 20 { 21 22 bool isHttpsRequest = IsHttpsRequest(context); 23 24 //在此写入您的处理程序实现。 25 HttpRequest Request = context.Request; 26 HttpResponse Response = context.Response; 27 SPWeb web = SPContext.Current.Web; 28 string appNo = System.IO.Path.GetFileNameWithoutExtension(Request.Url.AbsolutePath).ToLower(); 29 string url =context.Server.UrlEncode(Request["r"]); 30 string loginUrl = Request["l"]; 31 32 33 if (web.CurrentUser != null) 34 { 35 // Response.Write(web.CurrentUser.LoginName); 36 string userName = web.CurrentUser.Name; 37 userName = userName.Substring(userName.LastIndexOf('|') + 1); 38 39 40 // 检验该应用程序编码是否存在 41 System.Data.DataTable Appdb = SQLHelp.GetApplicationInfo(appNo); 42 if (Appdb == null || Appdb.Rows.Count == 0) 43 { 44 Response.Write("跳转地址有错误,请检查"); 45 Response.End(); 46 } 47 48 //写登录日志 49 SQLHelp.InsertLoginLog(userName, Request.UserHostAddress, appNo, true); 50 51 52 53 54 //如果不存在登录处理页,读取数据库默认的 55 if (string.IsNullOrEmpty(loginUrl)) loginUrl = Appdb.Rows[0]["LoginUrl"].ToString(); 56 57 58 } 59 60 //查看应该系统是否是用的是ad用户 61 if (Convert.ToBoolean(Appdb.Rows[0]["IsAD"]) == true) 62 { 63 64 object adPwd = SQLHelp.GetAdpassWord(userName); 65 userName = DESEncrypt.DesEncrypt(userName); 66 if (adPwd == null) Response.Write("ad用户错误,请联系管理员"); 67 68 string redirectUrl = string.Format("{0}?u={1}&p={2}&r={3}", loginUrl, context.Server.UrlEncode(userName), context.Server.UrlEncode(adPwd.ToString()), url); 69 // redirectUrl = context.Server.HtmlEncode(redirectUrl); 70 Response.Redirect(redirectUrl); 71 } 72 else 73 { 74 //非ad用户获取用户名 75 System.Data.DataTable appUserInfo = SQLHelp.GetAppAccount(userName, appNo); 76 77 //如果能在usermaping 表查到用户,就跳转登录页 78 if (appUserInfo != null&&appUserInfo.Rows.Count>0) 79 { 80 string u=context.Server.UrlEncode(appUserInfo.Rows[0]["userName"].ToString()); 81 string p=context.Server.UrlEncode(appUserInfo.Rows[0]["PassWord"].ToString()); 82 string redirectUrl = string.Format("{0}?u={1}&p={2}&r={3}", loginUrl,u ,p , url); 83 Response.Redirect(redirectUrl); 84 85 } 86 else 87 { //否则跳转用户usermaping表. 88 loginUrl = context.Server.UrlEncode(loginUrl); 89 string str = string.Format("/_layouts/ManageUserMapping.aspx?a={0}&l={1}&r={2}", appNo, loginUrl, url); 90 Response.Redirect(str); 91 } 92 } 93 94 } 95 96 //如果没有登录,跳转登录页 97 else 98 { 99 100 Response.Redirect("/_forms/default.aspx" ); 101 102 } 103 } 104 105 #endregion 106 }
然后,我们用.net,网站实现了一个基类.那个类通过重写oninit 函数,首先会 去检测改用户有没有登录,如果没有登录,将跳转到单点登录中心去获取登录的用户名和密码,获取后实现单点登录.登录完后就可以正常使用了.
我们看看基类实现吧.
protected override void OnInit(EventArgs e) { //检测是单点登录中心跳转回来的页面 string userName = HttpContext.Current.Request["u"]; if (string.IsNullOrEmpty(userName) ) { //没有登录,跳转到门户登录页 //string loginUrl = "http://" + Request.Url.Authority + Request.Url.AbsolutePath; string returnUrl = HttpContext.Current.Request.Url.AbsoluteUri; Session["rrrr"] = returnUrl; //特殊字符处理 returnUrl = returnUrl.Replace("&", "_,_"); string url = string.Format("{0}?r={1}&l={2}", SSOUrl, returnUrl, loginUrl); HttpContext.Current.Response.Redirect(url); } else //登录处理,保存session { string userID = DESEncrypt.DesDecrypt(userName); //登录处理 this.LoadUserInfo(userID); string r = HttpContext.Current.Request["r"]; if (r != null) { r = r.Replace("_,_", "&"); HttpContext.Current.Response.Redirect(r); } else { if (Session["rrrr"] != null) HttpContext.Current.Response.Redirect(Session["rrrr"].ToString()); else { HttpContext.Current.Response.Redirect(SSOUrl); } } } }
当时由于时间关系,这个安全性方面,还是有加强的地方.我们实现这方法一个最大好处.就是做了很好的封装性.这段代码是我们在基类里的,用了2年多,我还很多同事都还不知道我们在哪里实现单点登录的.
对于其他java系统,实现的原理也是跟这个差不多. 好,下面我再介绍一下,这种方案的退出以及它的代码.