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

为什么80%的码农都做不了架构师?>>>   hot3.png

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

      为方便清晰描述,先定义几个名词,本文中出现之处均为如下含义。

      主站:Passport集中验证服务器 http://www.passport.com/ 。
      分站:http://www.a.com/、http://www.b.com/、http://www.c.com/ 
      凭证:用户登录后产生的数据标识,用于识别授权用户,可为多种方式,DEMO中主站我使用的是Cache,分站使用Session。
      令牌:由Passport颁发可在各分站中流通的唯一标识。
      OK,现在描述一下单点登录的过程:
      情形一、匿名用户:匿名用户访问分站a上的一个授权页面,首先跳转到主站让用户输入帐号、密码进行登录,验证通过后产生主站凭证,同时产生令牌,跳转回分 站a,此时分站a检测到用户已持有令牌,于是用令牌再次去主站获取用户凭证,获取成功后允许用户访问该授权页面。同时产生分站a的本地凭证,当该用户需要 再次验证时将先检查本地凭证,以减少网络交互。
      情形二、在分站a登录的用户访问分站b:因为用户在分站a登录过,已持有令牌,所以分站b会用令牌去主站获取用户凭证,获取成功后允许用户访问授权页面。同时产生分站b的本地凭证。

      设计完成后,接下来是方案实现的一些关键点:
      令牌:令牌 由主站颁发,主站颁发令牌同时生成用户凭证,并记录令牌与用户凭证之间的对应关系,以根据用户提供的令牌响应对应的凭证;令牌要在各跨域分站中进行流通, 所以DEMO中令牌我使用主站的Cookie,并指定Cookie.Domain="passport.com"。各分站如何共享主站的Cookie?从 分站Redirect到主站页面,然后该页面读取Cookie并以URL参数方式回传即可,可在DEMO代码中查看详细实现,当然如果哪位有更好的令牌实 现方式也拿出来分享。

//产生令牌
string tokenValue = Guid.NewGuid().ToString().ToUpper();
HttpCookie tokenCookie = new HttpCookie("Token");
tokenCookie.Values.Add("Value", tokenValue);
tokenCookie.Domain = "passport.com";
Response.AppendCookie(tokenCookie);
      主站凭证:主站凭证是一个关系表,包含了三个字段:令牌、凭证数据、过期时间。有多种实现方式可供选择,要求可靠的话用数据库,要求性能的话用Cache,DEMO中我使用的是Cache中的DataTable。如下代码所示:

/// <summary>
/// 初始化数据结构
/// </summary>
/// <remarks>
/// ----------------------------------------------------
/// | token(令牌) | info(用户凭证) | timeout(过期时间) |
/// |--------------------------------------------------|
/// </remarks>
private static void cacheInit()
{if (HttpContext.Current.Cache["CERT"] == null){DataTable dt = new DataTable();dt.Columns.Add("token", Type.GetType("System.String"));dt.Columns["token"].Unique = true;dt.Columns.Add("info", Type.GetType("System.Object"));dt.Columns["info"].DefaultValue = null;dt.Columns.Add("timeout", Type.GetType("System.DateTime"));dt.Columns["timeout"].DefaultValue = DateTime.Now.AddMinutes(double.Parse(System.Configuration.ConfigurationManager.AppSettings["timeout"]));DataColumn[] keys = new DataColumn[1];keys[0] = dt.Columns["token"];dt.PrimaryKey = keys;//Cache的过期时间为 令牌过期时间*2HttpContext.Current.Cache.Insert("CERT", dt, null, DateTime.MaxValue, TimeSpan.FromMinutes(double.Parse(System.Configuration.ConfigurationManager.AppSettings["timeout"]) * 2));}
}



      分站凭证:分站凭证主要用于减少重复验证时网络的交互,比如用户已在分站a上登录过,当他再次访问分站a时,就不必使用令牌去主站验证了,因为分站a已有该用户的凭证。分站凭证相对比较简单,使用Session、Cookie均可。

      分站SSO页面基类:分站使用SSO的页面会做一系列的逻辑判断处理,如文章开头的流程图。如果有多个页面的话不可能为每个页写一个这样的逻辑,OK,那么把这套逻辑封装成一个基类,凡是要使用SSO的页面继承该基类即可。如下代码所示:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;namespace SSO.SiteA.Class
{/// <summary>/// 授权页面基类/// </summary>public class AuthBase : System.Web.UI.Page{protected override void OnLoad(EventArgs e){if (Session["Token"] != null){//分站凭证存在Response.Write("恭喜,分站凭证存在,您被授权访问该页面!");}else{//令牌验证结果if (Request.QueryString["Token"] != null){if (Request.QueryString["Token"] != "$Token$"){//持有令牌string tokenValue = Request.QueryString["Token"];//调用WebService获取主站凭证SSO.SiteA.RefPassport.TokenService tokenService = new SSO.SiteA.RefPassport.TokenService();object o = tokenService.TokenGetCredence(tokenValue);if (o != null){//令牌正确Session["Token"] = o;Response.Write("恭喜,令牌存在,您被授权访问该页面!");}else{//令牌错误Response.Redirect(this.replaceToken());}}else{//未持有令牌Response.Redirect(this.replaceToken());}}//未进行令牌验证,去主站验证else{Response.Redirect(this.getTokenURL());}}base.OnLoad(e);}/// <summary>/// 获取带令牌请求的URL/// 在当前URL中附加上令牌请求参数/// </summary>/// <returns></returns>private string getTokenURL(){string url = Request.Url.AbsoluteUri;Regex reg = new Regex(@"^.*\?.+=.+$");if (reg.IsMatch(url))url += "&Token=$Token$";elseurl += "?Token=$Token$";return "http://www.passport.com/gettoken.aspx?BackURL=" + Server.UrlEncode(url);}/// <summary>/// 去掉URL中的令牌/// 在当前URL中去掉令牌参数/// </summary>/// <returns></returns>private string replaceToken(){string url = Request.Url.AbsoluteUri;url = Regex.Replace(url, @"(\?|&)Token=.*", "", RegexOptions.IgnoreCase);return "http://www.passport.com/userlogin.aspx?BackURL=" + Server.UrlEncode(url);}}//end class
}



      用户退出:用户退出时分别清空主站凭证与当前分站凭证。如果要求A站点退出,B、C站点也退出,可自行扩展接口清空每个分站凭证。
      主站过期凭证/令牌清除:定时清除(DataTable)Cache[“CERT”]中timeout字段超过当前时间的记录。

1.IIS中配置站点

配置4个站点指向相应的目录,并分别指定4个站点的主机头:

http://www.passport.com/

http://www.a.com/

http://www.b.com/

http://www.c.com/ 

2.修改hosts文件以将域名解析到本地站点

127.0.0.1          http://www.passport.com/

127.0.0.1          http://www.a.com/

127.0.0.1          http://www.b.com/

127.0.0.1          http://www.c.com/

转载于:https://my.oschina.net/ind/blog/416103

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在android中ScrollView嵌套ScrollView解决方案

文章转载自&#xff1a;http://www.jb51.net/article/33054.htm大家好&#xff0c;众所周知&#xff0c;android里两个相同方向的ScrollView是不能嵌套的&#xff0c;那要是有这样的需求怎么办,接下来为您介绍解决方法&#xff0c;感兴趣的朋友可以了解下大家好&#xff0c;众所…

Cucumber 入门一

&#xff08;转自&#xff1a;http://www.cnblogs.com/jarodzz/archive/2012/07/02/2573014.html&#xff09; 第一次看到Cucumber和BDD&#xff08;Behavior Driven Development, 行为驱动开发&#xff09;&#xff0c;是在四年前。那时才開始工作&#xff0c;对软件測试工具相…

Java中这7个方法,一不小心就用错了!

最近我们通过sonar静态代码检测&#xff0c;同时配合人工代码review&#xff0c;发现了项目中很多代码问题。除了常规的bug和安全漏洞之外&#xff0c;还有几处方法用法错误&#xff0c;引起了我极大的兴趣。我为什么会对这几个方法这么感兴趣呢&#xff1f;因为它们极具迷惑性…

这样设置,让你的 IDEA 好看到爆炸

今天这期我们来分享几个美化 IDEA 设置技巧&#xff0c;让你的 IDEA 与众不同。首先我们来看下 IDEA 默认设置&#xff0c;虽然不丑&#xff0c;但就是太单调&#xff0c;千篇一律。默认主题接着&#xff0c;我们来看下美化以后的界面&#xff0c;总体看起来是不是比默认好看了…

RabbitMQ 集群

2019独角兽企业重金招聘Python工程师标准>>> Clustering Guide A RabbitMQ broker is a logical grouping of one or several Erlang nodes, each running the RabbitMQ applicationand sharing users, virtual hosts, queues, exchanges, etc. Sometimes we refer …

使用uuid作为数据库主键,被技术总监怼了!

一、前言在日常开发中&#xff0c;数据库中主键id的生成方案&#xff0c;主要有三种数据库自增ID采用随机数生成不重复的ID采用jdk提供的uuid对于这三种方案&#xff0c;我发现在数据量少的情况下&#xff0c;没有特别的差异&#xff0c;但是当单表的数据量达到百万级以上时候&…

ThreadLocal不好用?那是你没用对!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在 Java 中&#xff0c;如果要问哪个类使用简单&#xff0c;但用好最不简单&#xff1f;我想你的脑海中一定会浮现出一次词—…

记一则js替换字符串的问题

2019独角兽企业重金招聘Python工程师标准>>> 软件的一处功能用到EasyUI的表单提交&#xff0c;返回一串字符串&#xff0c;这串字符串里有一段HTML代码&#xff0c;正常的情况下这段HTML代码里的双引号“ 是用 \ 转义过的。在IE中没问题&#xff0c;但是在Firefox和…

『图解Java并发』面试必问的CAS原理你会了吗?

在并发编程中我们都知道i操作是非线程安全的&#xff0c;这是因为 i操作不是原子操作。如何保证原子性呢&#xff1f;常用的方法就是加锁。在Java语言中可以使用 Synchronized和CAS实现加锁效果。Synchronized是悲观锁&#xff0c;线程开始执行第一步就是获取锁&#xff0c;一旦…

SimpleDateFormat线程不安全的5种解决方案!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;1.什么是线程不安全&#xff1f;线程不安全也叫非线程安全&#xff0c;是指多线程执行中&#xff0c;程序的执行结果和预期的…

mac地址漂移flapping的前因后果

一、什么是mac地址flapping?mac地址漂移是指&#xff1a;在同一个vlan内&#xff0c;mac地址表项的出接口出现变更。如图&#xff1a;二、产生的原因1、因为环路或VRRP切换&#xff0c;导致的MAC地址漂移告警。&#xff08;不予关注&#xff09;2、因为无线用户漫游&#xff0…

时间转换竟多出1年!Java开发中的20个坑你遇到过几个?

前言最近看了极客时间的《Java业务开发常见错误100例》&#xff0c;再结合平时踩的一些代码坑&#xff0c;写写总结&#xff0c;希望对大家有帮助&#xff0c;感谢阅读~1. 六类典型空指针问题包装类型的空指针问题级联调用的空指针问题Equals方法左边的空指针问题ConcurrentHas…

Oracle RAC Failover 详解

2019独角兽企业重金招聘Python工程师标准>>> Oracle RAC 同时具备HA(High Availiablity) 和LB(LoadBalance). 而其高可用性的基础就是Failover(故障转移). 它指集群中任何一个节点的故障都不会影响用户的使用&#xff0c;连接到故障节点的用户会被自动转移到健康节…

一个ThreadLocal和面试官大战30个回合

开场杭州某商务楼里&#xff0c;正发生着一起求职者和面试官的battle。面试官&#xff1a;你先自我介绍一下。安琪拉&#xff1a;面试官你好&#xff0c;我是草丛三婊&#xff0c;最强中单&#xff08;妲己不服&#xff09;&#xff0c;草地摩托车车手&#xff0c;第21套广播体…

图文并茂的聊聊Java内存模型!

在面试中&#xff0c;面试官经常喜欢问&#xff1a;『说说什么是Java内存模型(JMM)&#xff1f;』面试者内心狂喜&#xff0c;这题刚背过&#xff1a;『Java内存主要分为五大块&#xff1a;堆、方法区、虚拟机栈、本地方法栈、PC寄存器&#xff0c;balabala……』面试官会心一笑…

AngularJS入门心得2——何为双向数据绑定

前言&#xff1a;谁说Test工作比较轻松&#xff0c;最近在熟悉几个case&#xff0c;差点没疯。最近又是断断续续的看我的AngularJS&#xff0c;总觉得自己还是没有入门&#xff0c;可能是自己欠前端的东西太多了&#xff0c;看不了几行代码就有几个常用函数不熟悉的。看过了大漠…

Java中那些内存泄漏的场景!

虽然Java程序员不用像C/C程序员那样时刻关注内存的使用情况&#xff0c;JVM会帮我们处理好这些&#xff0c;但并不是说有了GC就可以高枕无忧&#xff0c;内存泄露相关的问题一般在测试的时候很难发现&#xff0c;一旦上线流量起来可能马上就是一个诡异的线上故障。内存泄露定义…

ThreadLocal内存溢出代码演示和原因分析!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;前言ThreadLocal 翻译成中文是线程本地变量的意思&#xff0c;也就是说它是线程中的私有变量&#xff0c;每个线程只能操作自…

彻夜怒肝!Spring Boot+Sentinel+Nacos高并发已撸完,快要裂开了!

很多人说程序员是最容易实现财富自由的职业&#xff0c;也确实&#xff0c;比如字节 28 岁的程序员郭宇不正是从普通开发一步步做起的吗&#xff1f;回归行业现状&#xff0c;当开发能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。最近我也一直在思考这个…

湖南多校对抗5.24

据说A,B,C题都比较水这里就不放代码了 D:Facility Locations 然而D题是一个脑经急转弯的题&#xff1a;有m行&#xff0c;n列&#xff0c;每个位置有可能为0&#xff0c;也可能不为0&#xff0c;问最多选K行是不是可以使得每一列都至少有一个0&#xff0c;其中代价c有个约束条件…