.NET单点登陆的实现方法及思路

系统的基本架构
   我们假设一个系统System包含Service客户服务中心、Shop网上购物中心和Office网上办公中心三个独立的网站。 Service管理客户的资料,登录和注销过程。不论客户访问System的任何一个页面,系统都会转到登录界面,在用户登录后,系统会自动转会到客户上 次请求的页面。并且用户此后可以在System中无缝切换。不需要再次进行登录。即在System中实现单点登录SSO(Single Sign-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>
<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

(0)

相关推荐

  • 如何在不同.net版本实现单点登录

    所谓单点登录(Single Sign On就是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.其实对于程序员在技术上要实现就得就是多个不同域名间共享cookie的问题. 最近在为ERP添加一个部署在另一台机器上,链接到原有老系统中的子项目,调用原有老项目中的Login实现单点登录,尝试了N次屡试不成,最后确定问题,是,.net2.0与4.0中对cookie的加密/解密方法由此差异,于是经过研究,重写实现了一个可以在不同.net版本中实现单点登录的简单方法. 1,共用登陆页代

  • 基于.Net的单点登录(SSO)实现解决方案

    前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助.SSO的解决方案很多,但搜索结果令人大失所望,大部分是相互转载,并且描述的也是走马观花. 闲话少叙,进入正题,我的想法是使用集中验证方式,多个站点集中Passport验证. 如下图所示:  为方便清晰描述,先定义几个名词,本文中出现之处均为如下含义. 主站:Passport集中验证服务器 http://www.passport.com/ .

  • 一个简单的asp.net 单点登录实现

    以下是实现的效果图:  首先上图的点击火车订票链接,就会打开http://学生信息平台网站/LoginToTrainSite.asa页面. LoginToTrainSite.asa页面的大致代码如下: 复制代码 代码如下: <% Response.Buffer = True Response.ExpiresAbsolute = Now() - 1 Response.Expires = 0 Response.CacheControl = "no-cache" Response.Ad

  • asp.net 简单单点登录技术分析

    代码如下: 复制代码 代码如下: ///单点登录(Single Sign On) public void SSOMethods(string username, string password) { //判断登录情况 此处方法省略-- int result = CheckLogin(username, password); if(result>0) { //唯一标识,可自行设定 string key = string.Format("{0}_{1}",username, pass

  • 在ASP.NET 中实现单点登录

    出自:[孟宪会之精彩世界] 发布日期:2005年1月27日 8点48分0秒 [有删改]  由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录.在ASP.NET中实现单点登录其实很简单,下面就把主要的方法和全部代码进行分析.   实现思路   利用Cache的功能,我们把用户的登录信息保存在Cache中,并设置过期时间为Session失效的时间,因此,一旦Session失效,我们的Cache也过期:而Cache对所有的用户都可以访问,因此,用它保存用户

  • asp.net 1.1/ 2.0 中快速实现单点登陆

    问题:  网站有bbs.xxx.com / main.xxx.com / pay.xxx.com 这三个不同的二级域名站,要实现任何一二级域名处登陆,其他各二级域名的站均登陆. 解决办法: 设置cookie的domain属性. 详细介绍: 把保存用户登陆信息的cookie的域设置成一样即可.usercookie.Domain=".xxx.com"; 要注意,在域名前必须要加一个".".这个设置在登陆和退出的时候都需要. 比较普遍的做法自然是用一个专门负责用户登陆的类

  • .NET单点登陆的实现方法及思路

    系统的基本架构 我们假设一个系统System包含Service客户服务中心.Shop网上购物中心和Office网上办公中心三个独立的网站. Service管理客户的资料,登录和注销过程.不论客户访问System的任何一个页面,系统都会转到登录界面,在用户登录后,系统会自动转会到客户上 次请求的页面.并且用户此后可以在System中无缝切换.不需要再次进行登录.即在System中实现单点登录SSO(Single Sign-On). 我们知道,用户的即时状态通常是使用Application.Sess

  • SpringBoot跨系统单点登陆的实现方法

    什么是单点登陆 单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性.当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录.这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中.相同的,单一退出(single sign-off)就是指,只需要单一的退出动作,就可以结束对于多个系统的访问权限. 单点登陆带来的好处 降低访问

  • ASP.NET实现单点登陆(SSO)适用于多种情况

    第一种:同主域但不同子域之间实现单点登陆 Form验证其实是基于身份cookie的验证.客户登陆后,生成一个包含用户身份信息(包含一个ticket)的cookie,这个cookie的名字就是在web.config里Authentication节form设定的name信息,如 复制代码 代码如下: <authentication mode="Forms"> <forms loginUrl="login.aspx" name=".ASPXAU

  • asp.net简单实现单点登录(SSO)的方法

    本文实例讲述了asp.net简单实现单点登录(SSO)的方法.分享给大家供大家参考,具体如下: 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统 CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架(耶鲁大学开发)主要用于Java Php 有兴趣大家可以研究下.. 下面是一个简单实现单点登录的

  • PHP版单点登陆实现方案的实例

    摘要: 本文主要介绍了利用webservice,session,cookie技术,来进行通用的单点登录系统的分析与设计.具体实现语言为PHP.单点 登录,英文名为Single Sign On,简称为 SSO,是目前企业,网络业务的用户综合处理的重要组成部分.而SSO的定义,是在多个应用系统中,用户只需要登陆一次就可以访问所有相互信任的应用系 统. 动机: 用过ucenter的全站登录方式的朋友,应该都知道这是典型的观察者模式的解决方案.用户中心作为subject, 其所属observer的注册和

  • spring boot整合CAS Client实现单点登陆验证的示例

    本文介绍了spring boot整合CAS Client实现单点登陆验证的示例,分享给大家,也给自己留个笔记,具体如下: 单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要 登录一次 就可以访问所有相互信任的应用系统. CAS Client 负责处理对客户端受保护资源的访问请求,需要对请求方进行身份认证时,重定向到 CAS Server 进行认证.(原则上,客户端应用不再接受任何的用户名密码等

  • SpringBoot集成JWT实现登陆验证的方法详解

    1:首先,我们需要在项目中导入两个依赖: <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifa

  • GoLang jwt无感刷新与SSO单点登录限制解除方法详解

    目录 前言 为什么使用JWT Cookie和Session token (header.payload.signature) token 安全性 基于token安全性的处理 客户端与服务端基于无感刷新流程图 golang实现atoken和rtoken 颁发token 校验token 无感刷新token 完整实现代码 SSO(Single Sign On)单用户登录以及无感刷新token 实现思路 实战代码 小结 前言 为什么使用JWT Jwt提供了生成token以及token验证的方法,而tok

  • Springboot Vue实现单点登陆功能示例详解

    目录 正文 简单上个图 先分析下登陆要做啥 怎么落实? 上代码 接口: token生成部分 刷新token 验证token 正文 登陆是系统最基础的功能之一.这么长时间了,一直在写业务,这个基础功能反而没怎么好好研究,都忘差不多了.今天没事儿就来撸一下. 以目前在接触和学习的一个开源系统为例,来分析一下登陆该怎么做.代码的话我就直接CV了. 简单上个图 (有水印.因为穷所以没开会员) 先分析下登陆要做啥 首先,搞清楚要做什么. 登陆了,系统就知道这是谁,他有什么权限,可以给他开放些什么业务功能,

  • 使用ssh-keygen,实现免密码登陆linux的方法

    1  本机创建ssh密钥 ssh-keygen 2  拷贝公共密钥到"被登陆机"输入密码, scp  id_rsa.pub  root@10.35.0.35:~/.ssh/id_rsa.pub 3  ssh到"被登陆机"把公共密钥输入 "authorized_keys"(如果多个机器都需要使用rsa密钥认证登录此机器的话,将这些机器产生的公钥全部输入到)"authorized_keys" cat  id_rsa.pub >

随机推荐