【散分讨论】No.08-多系统单点登录(SSO)的实现 可用分有7000多了,准备散掉,讨论一些日常开发中经常遇到的,有争议的问题,希望大家踊跃发言,并欢迎各路高手指点迷津!每个问题100分,给发言最精彩的5个人。第八个:多系统单点登录(SSO)的实现好像有很多种技术,还有现成的产品,大家说说看在.Net环境下如何实现数据传输的安全性,如何实现大量数据的同步? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 YES,我们公司的系统就是这样的,只不过就是所有系统的用户名密码都是主系统的,登陆一个后保存Session,调用其他系统的时候查找Session就可以了 如果不是在同一个服务器上就不能用Session了吧?或者没用一个IE打开网站.B/S结构程序可以用Cookie.缺点安全性极低.比较可行的方式是用WebService来传递系统间信息.也可以用数据库.每次登陆则在一个公共库中保存登录信息.记录IP地址等客户端信息.其它网站或系统在开始的时候校验. 不过有缺点,要是单位上网,出口是一个IP.则不能正确登录.要是安全系数高,最可行的方式,还是生成一个软件密钥,或者用USB硬件密钥.然后由统一的CA系统控制登录.缺点造价高,最少要开发一个CA系统啊. 要安全,肯定还是用加密措施啊!这主要是传输上的安全!至于大量数据同步,我觉得没必要,异步有其特点,而且现在WEB上,你几乎看不到用异步和同步有多少差异!所以,传输还是要根据实际情况来做! 这里有人写过http://www.cnblogs.com/lovecherry/archive/2006/10/09/524510.htmlhttp://www.cnblogs.com/lovecherry/archive/2006/10/09/524510.html 系统的基本架构 我们假设一个系统System包含Service客户服务中心、Shop网上购物中心和Office网上办公中心三个独立的网站。Service管理客户的资料,登录和注销过程。不论客户访问System的任何一个页面,系统都会转到登录界面,在用户登录后,系统会自动转会到客户上次请求的页面。并且用户此后可以在System中无缝切换。不需要再次进行登录。即在System中实现单点登录SSO(Single Sign-On)。 我们知道,用户的即时状态通常是使用Application、Session、Cookie和存储的。而这些都是不能在程序中跨站点访问的。我们必需通过站点间相互通讯来确认用户的即时状态。 简单的实现 如图所示,该图描述了用户访问System的流程。 第一步,假设用户访问了Shop或Office的任何一个页面Any。该页面所在的网站将会检查用户的即时状态。如果用户已经登录了,则将Any页面的信息返回给用户。如果用户还没有登录,则自动转到Service的Validate页面,验证用户在Service状态。即Shop或Office向Service发出请求,要求Service返回用户的即时状态。 第二步,Validate验证用户的即时状态,如果用户已经登录了,则Service将用户的即时状态返回给Shop或Office的同步页面Synchronous,通知Shop或Office同步用户状态。如果用户没有登录,则自动转向Customer页面,提示用户登录。 第三步,用户完成登录过程,当用户成功登录后,自动转回Validate页面,通知Shop或Office的Synchronous进行用户状态的同步。 第四步,在用户状态同步完成后,在本地站点,用户状态成为在线状态,即可访问Any页面。 在上面的流程中。我们知道,不管用户访问哪个站点,用户只需要一次登录,就保证用户在Service的即时状态都是在线的,不会再需要进行第二次登录的过程。 现在我们的思路已经清楚,具体的实现我们将在代码分析中完成。 代码分析 从上面的流程中我们可以看出,系统中Shop和Office的代码是完全类似的。只要Shop可以实现,Office也可以同样的克隆。所以我们的重点分析的对象是Shop和Service的代码。 数码精品,购物零风险 同方笔记本新品体验 “90天”征服女人! 性感女鞋挡不住的诱惑 1、Shop的Web.config和Project.cs 在Shop的Web.config里,我们配置了Service站点和Shop站点,以方便我们在部署时方便修改。<appsettings><add key="Service" value="http://localhost:8001" /><add key="WebSite" value="http://localhost:8002" /></appsettings> 在Project类里进行引用。using System;using System.Configuration;namespace Amethysture.SSO.Shop{ public class Project { public static string Service = ConfigurationSettings.AppSettings["Service"]; public static string WebSite = ConfigurationSettings.AppSettings["WebSite"]; }} 2、Shop的Global.cs Shop的Global.cs定义了四个Session变量,UserID用来标识用户身份。Pass标识用户即时状态,Security用于保存往来Service和Shop的通讯不是被仿冒的。Url保存了上次请求的页面,以保证在用户登录后能转到用户请求的页面。 protected void Session_Start(Object sender, EventArgs e){ this.Session.Add("UserID", 0); this.Session.Add("Pass", false); this.Session.Add("Security", ""); this.Session.Add("Url", "");} 3、Shop的Any.cs Shop的Any.cs并没有包含代码,因为Any类从Page继承而来,为了代码分析方便,我们将代码集中到Page.cs中。using System;using System.Web;namespace Amethysture.SSO.Shop{ public class Any : Amethysture.SSO.Shop.Page { }} 4、Shop的Page.cs Page类有两个方法,CustomerValidate和Initialize。CustomerValidate用户检查用户的即时状态,而Initialize是页面登录后发送给用户的信息。我们的重点是CustomerValidate。 CustomerValidate是一个非常简单的流程,用条件语句检查Pass的状态,如果Pass为否,则表示用户没有登录,页面跳转到Service的Validate页面中。我们要分析的是其中保存的Url和递交的WebSite和Security几个参数。Url的作用在前面已经讲清楚了,只是为了保证用户登录后能回到原来的页面。而WebSite是为了保证该站点是被Service所接受的,并且保证Service知道是哪个站点请求了用户即时状态。因为这个例子是个简单的例子,在后面的Validate里没有验证WebSite是否是接受的请求站点,但是在实际应用中应该验证这一点,因为Shop和Service等同于服务器和客户端,服务器出于安全考虑必须要检查客户端是否是被允许的。Security是非常重要的一点。Shop对Service发送的是请求,不需要保证该请求没有被篡改,但是在Service应答Shop请求时就必须要保证应答的数据没有被篡改了。Security正是为了保证数据安全而设计的。 在代码中,Security是通过Hash一个随机产生的数字生成的。具有不确定性。和保密性。我们可以看到,Security同时保存在Session中和发送给Service。我们把这个Security当作明文。在后面我们可以看到,Security在Service经过再一次Hash后作为密文发送回Shop。如果我们将Session保存的Security经过同样的Hash方法处理后等到的字符串如果和Service返回的密文相同,我们就能够在一定程度上保证Service应答的数据是没有经过修改的。using System;using System.Web;using System.Security.Cryptography;using System.Text;namespace Amethysture.SSO.Shop{ public class Page : System.Web.UI.Page { private void CustomerValidate() { bool Pass = (bool) this.Session["Pass"]; if (!Pass) { string Security = ""; Random Seed = new Random(); Security = Seed.Next(1, int.MaxValue).ToString(); byte[] Value; UnicodeEncoding Code = new UnicodeEncoding(); byte[] Message = Code.GetBytes(Security); SHA512Managed Arithmetic = new SHA512Managed(); Value = Arithmetic.ComputeHash(Message); Security = ""; foreach(byte o in Value) { Security += (int) o + "O"; } this.Session["Security"] = Security; this.Session["Url"] = this.Request.RawUrl; this.Response.Redirect(Project.Service + "/Validate.aspx?WebSite=" + Project.WebSite + "&Security=" + Security); } } protected virtual void Initialize() { this.Response.Write("<html>"); this.Response.Write("<head>"); this.Response.Write("<title>Amethysture SSO Project</title>"); this.Response.Write("<link rel=stylesheet type=\"text/css\" href=\"" + project.website + "/Default.css\">"); this.Response.Write("</head>"); this.Response.Write("<body>"); this.Response.Write("<iframe width=\"0\" height=\"0\" src=\"" + project.service + "/Customer.aspx\"></iframe>"); this.Response.Write("<div align=\"center\">"); this.Response.Write("Amethysture SSO Shop Any Page"); this.Response.Write("</div>"); this.Response.Write("</body>"); this.Response.Write("</html>"); } protected override void OnInit(EventArgs e) { base.OnInit(e); this.CustomerValidate(); this.Initialize(); this.Response.End(); } }} 5、Service的Global.cs 现在我们页面转到了Service的Validate页面,我们转过来看Service的代码。在Global中我们同样定义了四个Session变量,都和Shop的Session用处类似。WebSite是保存请求用户即时状态的站点信息。以便能在登录后返回正确的请求站点。 protected void Session_Start(Object sender, EventArgs e){ this.Session.Add("UserID", 0); this.Session.Add("Pass", false); this.Session.Add("WebSite", ""); this.Session.Add("Security", "");} 6、Service的Validate.cs 首先,将Shop传递过来的参数保存到Session中。如果用户没有登录,则转到Customer页面进行登录。如果用户已经登录了。则将用户即时状态传回给Shop站点。如上所述,这里将Security重新Hash了一次传回给Shop,以保证数据不被纂改。private void CustomerValidate(){ bool Pass = (bool) this.Session["Pass"]; if ((this.Request.QueryString["WebSite"] != null) && (this.Request.QueryString["WebSite"] != "")) { this.Session["WebSite"] = this.Request.QueryString["WebSite"]; } if ((this.Request.QueryString["Security"] != null) && (this.Request.QueryString["Security"] != "")) { this.Session["Security"] = this.Request.QueryString["Security"]; } if (Pass) { string UserID = this.Session["UserID"].ToString(); string WebSite = this.Session["WebSite"].ToString(); string Security = this.Session["Security"].ToString(); byte[] Value; UnicodeEncoding Code = new UnicodeEncoding(); byte[] Message = Code.GetBytes(Security); SHA512Managed Arithmetic = new SHA512Managed(); Value = Arithmetic.ComputeHash(Message); Security = ""; foreach(byte o in Value) { Security += (int) o + "O"; } this.Response.Redirect(WebSite + "/Synchronous.aspx?UserID=" + UserID + "&Pass=True&Security=" + Security); } else { this.Response.Redirect("Customer.aspx"); }} 7、Service的Customer.cs和Login.cs Customer主要的是一个用于登录的表单,这里就不贴出代码了。这里分析一下Login的一段代码,这段代码是当登录是直接在Service完成的(WebSite为空值),则页面不会转到Shop或Office站点。所以应该暂停在Service站点。系统如果比较完美,这里应该显示一组字系统的转向链接。下面我们看到,当Pass为真时,页面转回到Validate页面,通过上面的分析,我们知道,页面会转向Shop的Synchronous页面,进行用户状态的同步。if (Pass){ if ((this.Session["WebSite"].ToString() != "") && (this.Session["Security"].ToString() != "")) { this.Response.Redirect("Validate.aspx"); } else { this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write("Pass"); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); }}else{ this.Response.Redirect("Customer.aspx");} 8、Shop的Synchronous.cs 好了,我们在Service中完成了登录,并把用户状态传递回Shop站点。我们接着看用户状态是怎么同步的。首先,如果Session里的Security是空字符串,则表示Shop站点没有向Service发送过请求,而Service向Shop发回了请求,这显然是错误的。这次访问是由客户端伪造进行的访问,于是访问被拒绝了。同样Security和InSecurity不相同,则表示请求和应答是不匹配的。可能应答被纂改过了,所以应答同样被拒绝了。当检验Security通过后,我们保证Serive完成了应答,并且返回了确切的参数,下面就是读出参数同步Shop站点和Service站点的用户即时状态。string InUserID = this.Request.QueryString["UserID"];string InPass = this.Request.QueryString["Pass"];string InSecurity = this.Request.QueryString["Security"];string Security = this.Session["Security"].ToString();if (Security != ""){ byte[] Value; UnicodeEncoding Code = new UnicodeEncoding(); byte[] Message = Code.GetBytes(Security); SHA512Managed Arithmetic = new SHA512Managed(); Value = Arithmetic.ComputeHash(Message); Security = ""; foreach(byte o in Value) { Security += (int) o + "O"; } if (Security == InSecurity) { if (InPass == "True") { this.Session["UserID"] = int.Parse(InUserID); this.Session["Pass"] = true; this.Response.Redirect(this.Session["Url"].ToString()); } } else { this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write("数据错误"); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); }}else{ this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write(""); this.Response.Write("访问错误"); this.Response.Write(""); this.Response.Write(""); this.Response.Write("");} 9、Shop的Page.cs 我们知道,页面在一段时间不刷新后,Session会超时失效,在我们一直访问Shop的时候怎么才能保证Service的Session不会失效呢?很简单,我们返回来看Shop的Page.cs。通过在所有Shop的页面内都用<iframe>嵌套Service的某个页面,就能保证Service能和Shop的页面同时刷新。需要注意的一点是Service的Session必须保证不小于所有Shop和Office的Session超时时间。这个在Web.config里可以进行配置。 this.Response.Write("<iframe width=\"0\" height=\"0\" src=\"" + project.service + "/Customer.aspx\"></iframe>"); 总结 一次完整的登录完成了。我们接着假设一下现在要跳到Office的Any页面,系统会进行怎样的操作呢?Any(用户没有登录)->Validate(用户已经登录)->Synchronous(同步)->Any。也就是说这次,用户没有进行登录的过程。我们通过一次登录,使得Service的用户状态为登录,并且不管有多少个网站应用,只要这些网站都保证符合Shop的特性,这些网站就都能保持Service的用户状态,同时能通过Service获得用户的状态。也就是说我们实现了SSO。 up up up up up up 我去年做了一个,将公司所有的产品都集成起来,是和CA合作,验证他们来做的,我们的系统从验证后的票据中得到相应信息和应用系统做接口。实现不是很难,主要是在传输过程中对票据安全性的保证,CA是用数字证书来实现的,然后给我们提供读取的接口。系统的实现:C/S的只是在启动的时候首先去读取票据是否存在并通过验证,然后得到登录信息后跳过登录的页面。B/S同样在Global里面先进行取票据就ok了。封装了几个com组件,还是比较好用的。 CA的票据是写在系统的内存中,然后用的时候再从里面取出来。只是听CA的人说的,具体实现不是很清楚。 问题还是解决不了,sleep会阻塞别的委托,急。。。 c#集体打印的问题 多线程窗体,如何访问? c#中GridView问题 C# 中webclient 错误,请高手指导 dataGird导出到EXCEL的问题 如何不用XML来实现树型结构的存取 AutoCompleteExtra.dll 这个问题一定要星星回答,不是星星顶顶也有分,不够再加哦~! 神啊,救救我吧 excel导出中奇怪的问题。 WinForm中ListBox.Items.Add()问题
B/S结构程序可以用Cookie.缺点安全性极低.
比较可行的方式是用WebService来传递系统间信息.也可以用数据库.每次登陆则在一个公共库中保存登录信息.记录IP地址等客户端信息.其它网站或系统在开始的时候校验. 不过有缺点,要是单位上网,出口是一个IP.则不能正确登录.要是安全系数高,最可行的方式,还是生成一个软件密钥,或者用USB硬件密钥.然后由统一的CA系统控制登录.缺点造价高,最少要开发一个CA系统啊.
http://www.cnblogs.com/lovecherry/archive/2006/10/09/524510.html
http://www.cnblogs.com/lovecherry/archive/2006/10/09/524510.html
代码分析 从上面的流程中我们可以看出,系统中Shop和Office的代码是完全类似的。只要Shop可以实现,Office也可以同样的克隆。所以我们的重点分析的对象是Shop和Service的代码。 数码精品,购物零风险 同方笔记本新品体验
“90天”征服女人! 性感女鞋挡不住的诱惑 1、Shop的Web.config和Project.cs 在Shop的Web.config里,我们配置了Service站点和Shop站点,以方便我们在部署时方便修改。<appsettings>
<add key="Service" value="http://localhost:8001" />
<add key="WebSite" value="http://localhost:8002" />
</appsettings> 在Project类里进行引用。using System;
using System.Configuration;namespace Amethysture.SSO.Shop
{
public class Project
{
public static string Service = ConfigurationSettings.AppSettings["Service"];
public static string WebSite = ConfigurationSettings.AppSettings["WebSite"];
}
} 2、Shop的Global.cs Shop的Global.cs定义了四个Session变量,UserID用来标识用户身份。Pass标识用户即时状态,Security用于保存往来Service和Shop的通讯不是被仿冒的。Url保存了上次请求的页面,以保证在用户登录后能转到用户请求的页面。 protected void Session_Start(Object sender, EventArgs e)
{
this.Session.Add("UserID", 0);
this.Session.Add("Pass", false);
this.Session.Add("Security", "");
this.Session.Add("Url", "");
} 3、Shop的Any.cs Shop的Any.cs并没有包含代码,因为Any类从Page继承而来,为了代码分析方便,我们将代码集中到Page.cs中。using System;
using System.Web;namespace Amethysture.SSO.Shop
{
public class Any : Amethysture.SSO.Shop.Page
{
}
} 4、Shop的Page.cs Page类有两个方法,CustomerValidate和Initialize。CustomerValidate用户检查用户的即时状态,而Initialize是页面登录后发送给用户的信息。我们的重点是CustomerValidate。 CustomerValidate是一个非常简单的流程,用条件语句检查Pass的状态,如果Pass为否,则表示用户没有登录,页面跳转到Service的Validate页面中。我们要分析的是其中保存的Url和递交的WebSite和Security几个参数。Url的作用在前面已经讲清楚了,只是为了保证用户登录后能回到原来的页面。而WebSite是为了保证该站点是被Service所接受的,并且保证Service知道是哪个站点请求了用户即时状态。因为这个例子是个简单的例子,在后面的Validate里没有验证WebSite是否是接受的请求站点,但是在实际应用中应该验证这一点,因为Shop和Service等同于服务器和客户端,服务器出于安全考虑必须要检查客户端是否是被允许的。Security是非常重要的一点。Shop对Service发送的是请求,不需要保证该请求没有被篡改,但是在Service应答Shop请求时就必须要保证应答的数据没有被篡改了。Security正是为了保证数据安全而设计的。 在代码中,Security是通过Hash一个随机产生的数字生成的。具有不确定性。和保密性。我们可以看到,Security同时保存在Session中和发送给Service。我们把这个Security当作明文。在后面我们可以看到,Security在Service经过再一次Hash后作为密文发送回Shop。如果我们将Session保存的Security经过同样的Hash方法处理后等到的字符串如果和Service返回的密文相同,我们就能够在一定程度上保证Service应答的数据是没有经过修改的。using System;
using System.Web;
using System.Security.Cryptography;
using System.Text;namespace Amethysture.SSO.Shop
{
public class Page : System.Web.UI.Page
{
private void CustomerValidate()
{
bool Pass = (bool) this.Session["Pass"];
if (!Pass)
{
string Security = "";
Random Seed = new Random();
Security = Seed.Next(1, int.MaxValue).ToString();
byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding();
byte[] Message = Code.GetBytes(Security);
SHA512Managed Arithmetic = new SHA512Managed();
Value = Arithmetic.ComputeHash(Message);
Security = "";
foreach(byte o in Value)
{
Security += (int) o + "O";
}
this.Session["Security"] = Security;
this.Session["Url"] = this.Request.RawUrl;
this.Response.Redirect(Project.Service + "/Validate.aspx?WebSite=" + Project.WebSite + "&Security=" + Security);
}
} protected virtual void Initialize()
{
this.Response.Write("<html>");
this.Response.Write("<head>");
this.Response.Write("<title>Amethysture SSO Project</title>");
this.Response.Write("<link rel=stylesheet type=\"text/css\" href=\"" + project.website + "/Default.css\">");
this.Response.Write("</head>");
this.Response.Write("<body>");
this.Response.Write("<iframe width=\"0\" height=\"0\" src=\"" + project.service + "/Customer.aspx\"></iframe>");
this.Response.Write("<div align=\"center\">");
this.Response.Write("Amethysture SSO Shop Any Page");
this.Response.Write("</div>");
this.Response.Write("</body>");
this.Response.Write("</html>");
} protected override void OnInit(EventArgs e)
{
base.OnInit(e);
this.CustomerValidate();
this.Initialize();
this.Response.End();
}
}
}
{
this.Session.Add("UserID", 0);
this.Session.Add("Pass", false);
this.Session.Add("WebSite", "");
this.Session.Add("Security", "");
} 6、Service的Validate.cs 首先,将Shop传递过来的参数保存到Session中。如果用户没有登录,则转到Customer页面进行登录。如果用户已经登录了。则将用户即时状态传回给Shop站点。如上所述,这里将Security重新Hash了一次传回给Shop,以保证数据不被纂改。private void CustomerValidate()
{
bool Pass = (bool) this.Session["Pass"];
if ((this.Request.QueryString["WebSite"] != null) && (this.Request.QueryString["WebSite"] != ""))
{
this.Session["WebSite"] = this.Request.QueryString["WebSite"];
}
if ((this.Request.QueryString["Security"] != null) && (this.Request.QueryString["Security"] != ""))
{
this.Session["Security"] = this.Request.QueryString["Security"];
}
if (Pass)
{
string UserID = this.Session["UserID"].ToString();
string WebSite = this.Session["WebSite"].ToString();
string Security = this.Session["Security"].ToString();
byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding();
byte[] Message = Code.GetBytes(Security);
SHA512Managed Arithmetic = new SHA512Managed();
Value = Arithmetic.ComputeHash(Message);
Security = "";
foreach(byte o in Value)
{
Security += (int) o + "O";
}
this.Response.Redirect(WebSite + "/Synchronous.aspx?UserID=" + UserID + "&Pass=True&Security=" + Security);
}
else
{
this.Response.Redirect("Customer.aspx");
}
} 7、Service的Customer.cs和Login.cs Customer主要的是一个用于登录的表单,这里就不贴出代码了。这里分析一下Login的一段代码,这段代码是当登录是直接在Service完成的(WebSite为空值),则页面不会转到Shop或Office站点。所以应该暂停在Service站点。系统如果比较完美,这里应该显示一组字系统的转向链接。下面我们看到,当Pass为真时,页面转回到Validate页面,通过上面的分析,我们知道,页面会转向Shop的Synchronous页面,进行用户状态的同步。if (Pass)
{
if ((this.Session["WebSite"].ToString() != "") && (this.Session["Security"].ToString() != ""))
{
this.Response.Redirect("Validate.aspx");
}
else
{
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("Pass");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
}
}
else
{
this.Response.Redirect("Customer.aspx");
} 8、Shop的Synchronous.cs 好了,我们在Service中完成了登录,并把用户状态传递回Shop站点。我们接着看用户状态是怎么同步的。首先,如果Session里的Security是空字符串,则表示Shop站点没有向Service发送过请求,而Service向Shop发回了请求,这显然是错误的。这次访问是由客户端伪造进行的访问,于是访问被拒绝了。同样Security和InSecurity不相同,则表示请求和应答是不匹配的。可能应答被纂改过了,所以应答同样被拒绝了。当检验Security通过后,我们保证Serive完成了应答,并且返回了确切的参数,下面就是读出参数同步Shop站点和Service站点的用户即时状态。string InUserID = this.Request.QueryString["UserID"];
string InPass = this.Request.QueryString["Pass"];
string InSecurity = this.Request.QueryString["Security"];string Security = this.Session["Security"].ToString();
if (Security != "")
{
byte[] Value;
UnicodeEncoding Code = new UnicodeEncoding();
byte[] Message = Code.GetBytes(Security);
SHA512Managed Arithmetic = new SHA512Managed();
Value = Arithmetic.ComputeHash(Message);
Security = "";
foreach(byte o in Value)
{
Security += (int) o + "O";
} if (Security == InSecurity)
{
if (InPass == "True")
{
this.Session["UserID"] = int.Parse(InUserID);
this.Session["Pass"] = true;
this.Response.Redirect(this.Session["Url"].ToString());
}
}
else
{
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("数据错误");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
}
}
else
{
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("访问错误");
this.Response.Write("");
this.Response.Write("");
this.Response.Write("");
} 9、Shop的Page.cs 我们知道,页面在一段时间不刷新后,Session会超时失效,在我们一直访问Shop的时候怎么才能保证Service的Session不会失效呢?很简单,我们返回来看Shop的Page.cs。通过在所有Shop的页面内都用<iframe>嵌套Service的某个页面,就能保证Service能和Shop的页面同时刷新。需要注意的一点是Service的Session必须保证不小于所有Shop和Office的Session超时时间。这个在Web.config里可以进行配置。 this.Response.Write("<iframe width=\"0\" height=\"0\" src=\"" + project.service + "/Customer.aspx\"></iframe>"); 总结 一次完整的登录完成了。我们接着假设一下现在要跳到Office的Any页面,系统会进行怎样的操作呢?Any(用户没有登录)->Validate(用户已经登录)->Synchronous(同步)->Any。也就是说这次,用户没有进行登录的过程。我们通过一次登录,使得Service的用户状态为登录,并且不管有多少个网站应用,只要这些网站都保证符合Shop的特性,这些网站就都能保持Service的用户状态,同时能通过Service获得用户的状态。也就是说我们实现了SSO。
实现不是很难,主要是在传输过程中对票据安全性的保证,CA是用数字证书来实现的,然后给我们提供读取的接口。
系统的实现:C/S的只是在启动的时候首先去读取票据是否存在并通过验证,然后得到登录信息后跳过登录的页面。B/S同样在Global里面先进行取票据就ok了。
封装了几个com组件,还是比较好用的。