单点登录在项目中的实现
最近在做一个登录功能,纠结了好几天,一直在找一个能优雅的实现单点登录的功能。博客园有看到某人写了又臭又长的八股文式的文章,没看到有价值的东西。
其实单点登录最终要解决的是多个不同域名间共享cookie的问题。但是要在不同域名间共享cookie是一件很困难的事情,要在某个域名下面种cookie就必须访问该
域名。网上有很多方法,看到的有动态创建iframe实现,在iframe里面访问某个域名的页面种下cookie,该方法需要写一些js代码,写起来有点累,所以我最终
选择了用页面跳转来实现,想不到效果比我预期的好很多,浏览器几乎看不出来有跳转的痕迹。
详细介绍下流程:
1. 项目有3个不同的域名,login.susucms.com, suhow.com, sigcms.com。其中login.susucms.com/login.aspx是登录页面。实现的功能是通过login.susucms.com/login.aspx登录后能够实现在访问其他域名也可以保持登录状态。
2. 在suhow.com和sigcms.com下分别添加一个sso.aspx的页面。
3. 当用户在login.susucms.com/login.aspx页面点击登录,服务器端通过验证后生成一个token,接着服务器端Response.Redirect到suhow.com/sso.aspx,suhow.com/sso.aspx立即验证这个token是否合法,如果合法则Reponse一个包含登录信息的cookie,然后Response.Redirect到sigcms.com/sso.aspx,sigcms.com/sso.aspx也验证这个token是否合法,如果合法则Reponse一个包含登录信息的cookie,然后销毁token,Response.Redirect到登录后的后台。
整个流程最核心的其实就是跳转。没有其他的了。经过测试,服务器端响应非常快,几乎感觉不到任何跳转,所以再多跳转几个域名,我想是没有什么大问题的。
简单代码:
1. login.susucms.com/login.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 | if (IsLogin) { var login = new CrossDomainLogin { Key = Guid.NewGuid().ToString(), CreateTime = DateTime.Now }; DataContext.CrossDomainLogins.InsertOnSubmit(login); DataContext.SubmitChanges(); WriteAuthenticationCookie(); Response.Redirect( "http://suhow.com/sso.aspx?key=" + login.Key); } |
2. suhow.com/sso.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | var key = Request.QueryString[ "key" ]; var login = DataContext.CrossDomainLogins.FirstOrDefault(i => i.Key == key); if (login != null ) { // key will be expired in 3 minutes if (DateTime.Now > login.CreateTime.AddMinutes(3)) { RemoveKey(login); // delete key from database Response.Redirect( "http://login.susucms.com/login.aspx" ); } else { WriteAuthenticationCookie(); Response.Redirect( "http://sigcms.com/sso.aspx?key=" + login.Key); } } else { // .... } |
3. sigcms.com/sso.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var key = Request.QueryString[ "key" ]; var login = DataContext.CrossDomainLogins.FirstOrDefault(i => i.Key == key); if (login != null ) { // key will be expired in 3 minutes if (DateTime.Now > login.CreateTime.AddMinutes(3)) { RemoveKey(login); // delete key from database Response.Redirect( "http://login.susucms.com/login.aspx" ); } else { WriteAuthenticationCookie(); RemoveKey(login); // delete key from database Response.Redirect( "http://login.susucms.com/admin/default.aspx" ); } } else { // .... } |
----------------更新-------------------
后面由于项目情况比较复杂,而站点用户后台是由iframe显示页面内容。所以最后跨域代码调整到后台页面执行。
key过期处理的代码就不贴了,大家各显神通了。
关于鹤冲天发的那个链接实际上不是用来实现跨域的。
1 var login = DataContext.CrossDomainLogins.FirstOrDefault(i => i.Key == key);
2 if (login != null)
3 {
4 ClientScript.RegisterClientScriptInclude("suhow", string.Format("http://suhow.com/sso.aspx?key={0}", login.Key));
5 ClientScript.RegisterClientScriptInclude("sigcms", string.Format("http://sigcms.com/sso.aspx?key={0}", login.Key));
6 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库