Csharp/C#教程:.NET单点登陆的实现方法及思路分享

上述就是C#学习教程:.NET单点登陆的实现方法及思路分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)! 系统的基本架构
  我们假设一个系统System包含Service客户服务中心、Shop网上购物中心和Office网上办公中心三个独立的网站。Service管理客户的资料,登录和注销过程。不论客户访问System的任何一个页面,系统都会转到登录界面,在用户登录后,系统会自动转会到客户上次请求的页面。并且用户此后可以在System中无缝切换。不需要再次进行登录。即在System中实现单点登录SSO(SingleSign-On)。
  我们知道,用户的即时状态通常是使用Application、Session、Cookie和存储的。而这些都是不能在程序中跨站点访问的。我们必需通过站点间相互通讯来确认用户的即时状态。
 简单的实现
  第一步,假设用户访问了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的代码。
  1、Shop的Web.config和Project.cs
  在Shop的Web.config里,我们配置了Service站点和Shop站点,以方便我们在部署时方便修改。
代码如下:
<appsettings>
<addkey=”Service”value=”https://localhost:8001″/>
<addkey=”WebSite”value=”https://localhost:8002″/>
</appsettings> 

 在Project类里进行引用。
代码如下:
usingSystem;
usingSystem.Configuration;
namespaceAmethysture.SSO.Shop
{
 publicclassProject
 {
  publicstaticstringService=ConfigurationSettings.AppSettings[“Service”];
  publicstaticstringWebSite=ConfigurationSettings.AppSettings[“WebSite”];
 }
}

  2、Shop的Global.cs
  Shop的Global.cs定义了四个Session变量,UserID用来标识用户身份。Pass标识用户即时状态,Security用于保存往来Service和Shop的通讯不是被仿冒的。Url保存了上次请求的页面,以保证在用户登录后能转到用户请求的页面。
代码如下:
protectedvoidSession_Start(Objectsender,EventArgse)
{
 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中。
代码如下:
usingSystem;
usingSystem.Web;
namespaceAmethysture.SSO.Shop
{
 publicclassAny: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应答的数据是没有经过修改的。
代码如下:
usingSystem;
usingSystem.Web;
usingSystem.Security.Cryptography;
usingSystem.Text;
namespaceAmethysture.SSO.Shop
{
 publicclassPage:System.Web.UI.Page
 {
  privatevoidCustomerValidate()
  {
   boolPass=(bool)this.Session[“Pass”];
   if(!Pass)
   {
    stringSecurity=””;
    RandomSeed=newRandom();
    Security=Seed.Next(1,int.MaxValue).ToString();
    byte[]Value;
    UnicodeEncodingCode=newUnicodeEncoding();
    byte[]Message=Code.GetBytes(Security);
    SHA512ManagedArithmetic=newSHA512Managed();
    Value=Arithmetic.ComputeHash(Message);
    Security=””;
    foreach(byteoinValue)
    {
     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);
   }
  }
  protectedvirtualvoidInitialize()
  {
   this.Response.Write(“<html>”);
   this.Response.Write(“<head>”); 
   this.Response.Write(“<title>AmethystureSSOProject</title>”);
   this.Response.Write(“<linkrel=stylesheettype=”text/css”href=””+project.website+”/Default.css”>”);
   this.Response.Write(“</head>”);
   this.Response.Write(“<body>”);
   this.Response.Write(“<iframewidth=”0″height=”0″src=””+project.service+”/Customer.aspx”></iframe>”);
   this.Response.Write(“<divalign=”center”>”);
   this.Response.Write(“AmethystureSSOShopAnyPage”);
   this.Response.Write(“</div>”);
   this.Response.Write(“</body>”);
   this.Response.Write(“</html>”);
  }
  protectedoverridevoidOnInit(EventArgse)
  {
   base.OnInit(e);
   this.CustomerValidate();
   this.Initialize();
   this.Response.End();
  }
 }
}

5、Service的Global.cs
  现在我们页面转到了Service的Validate页面,我们转过 看Service的代码。在Global中我们同样定义了四个Session变量,都和Shop的Session用处类似。WebSite是保存请求用户即时状态的站点信息。以便能在登录后返回正确的请求站点。
代码如下:
protectedvoidSession_Start(Objectsender,EventArgse)
{
 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,以保证数据不被纂改。
代码如下:
privatevoidCustomerValidate()
{
 boolPass=(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)
 {
  stringUserID=this.Session[“UserID”].ToString();
  stringWebSite=this.Session[“WebSite”].ToString();
  stringSecurity=this.Session[“Security”].ToString();
  byte[]Value;
  UnicodeEncodingCode=newUnicodeEncoding();
  byte[]Message=Code.GetBytes(Security);
  SHA512ManagedArithmetic=newSHA512Managed();
  Value=Arithmetic.ComputeHash(Message);
  Security=””;
  foreach(byteoinValue)
  {
   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站点 用户即时状态。
代码如下:
stringInUserID=this.Request.QueryString[“UserID”];
stringInPass=this.Request.QueryString[“Pass”];
stringInSecurity=this.Request.QueryString[“Security”];
stringSecurity=this.Session[“Security”].ToString();
if(Security!=””)
{
 byte[]Value;
 UnicodeEncodingCode=newUnicodeEncoding();
 byte[]Message=Code.GetBytes(Security);
 SHA512ManagedArithmetic=newSHA512Managed();
 Value=Arithmetic.ComputeHash(Message);
 Security=””;
 foreach(byteoinValue)
 {
  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(“<iframewidth=”0″height=”0″src=””+project.service+”/Customer.aspx”></iframe>”);

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/904893.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐