Asp.net单点登录解决方案
原文出处:http://www.cnblogs.com/wu-jian
主站:Passport集中验证服务器,DEMO中为:http://www.passport.com/
分站:http://www.a.com/、http://www.b.com/、http://www.c.com/
凭证:用户登录后产生的鉴权标识,用于识别授权用户。可为多种方式,DEMO中主站使用的是Cache,分站使用的是Session。
令牌:由Passport颁发可在各分站中流通的用户唯一鉴权标识,DEMO中使用的是Cookie。
核心逻辑
使用集中式身份验证,用户数据存放于Passport,各分站统一使用Passport进行登录和鉴权,如<图1>所示:
<图1>
<图2>
<图2>详细描述了单点登录逻辑与流程
流程一:匿名用户访问分站a
匿名用户访问分站a上的一个授权页面,首先跳转到主站通过帐号、密码进行登录鉴权,验证通过后产生主站凭证,同时产生令牌,跳转回分站a。
此时分站a检测到用户已持有令牌,于是用令牌再次去主站获取用户凭证,获取成功后允许用户访问该授权页面。同时产生分站a的本地凭证。
当该用户需要再次验证时将使用本地凭证,以减少网络交互。
流程二:在分站a登录的用户访问分站b
因为用户在分站a登录过,已持有令牌,所以分站b会用令牌去主站获取用户凭证,获取成功后允许用户访问授权页面。同时产生分站b的本地凭证。
实现关键点
令牌
令牌由主站颁发,主站颁发令牌同时生成用户凭证,并记录令牌与用户凭证之间的对应关系,以根据用户提供的令牌响应对应的凭证;
令牌要在各跨域分站中进行流通,DEMO中使用了Cookie,并指定Cookie.Domain="passport.com";
各分站如何共享主站的Cookie?从分站Redirect到主站页面,然后该页面读取Cookie并以URL参数方式回传即可,可在DEMO代码中查看详细实现。
//产生令牌
HttpCookie tokenCookie = new HttpCookie("Passport.Token");
tokenCookie.Domain = "passport.com";
//可使用自定义算法避免Cookie非法复制
//tokenCookie.Values.Add("Key", "加密算法");
tokenCookie.Values.Add("Value", tokenValue);
Response.AppendCookie(tokenCookie);
在之前的文章中有读者提到令牌(Cookie)被非法复制导致的安全问题,在此简单说明一下。
首先默认设置了Cookie为关闭浏览器即失效,也就是说用户在成功鉴权后持续打开浏览器的前提下才会导至令牌泄漏。
然后在Passport令牌的设计中有“过期时间”一项,也可以通过使用令牌的过期时间来确保令牌安全。
如果您觉得还不够,其实只需要在令牌验证时添加一些自定义逻辑,比如用时间、用户特征产生一个Hash值作为令牌的安全KEY。
文章主要针对SSO的逻辑,一些细节上的代码并未十全十美,读者可以根据实际需求进行完善。
主站凭证
主站凭证是一个关系表,包含了三个字段:令牌、用户凭证、过期时间。
主站凭证有多种实现方式可供选择,比如要求可靠的话可以使用数据库,要求性能的话可以使用Cache,DEMO中我使用的是Cache。如下代码所示:
/// <summary>
/// 初始化缓存数据结构
/// </summary>
/// <remarks>
/// ----------------------------------------------------
/// | token(令牌) | cert(用户凭证) | timeout(过期时间) |
/// |--------------------------------------------------|
/// </remarks>
private static void cacheInit()
{
if (HttpContext.Current.Cache["PASSPORT.TOKEN"] == null)
{
DataTable dt = new DataTable(); dt.Columns.Add("token", Type.GetType("System.String"));
dt.Columns["token"].Unique = true; dt.Columns.Add("cert", Type.GetType("System.Object"));
dt.Columns["cert"].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的过期时间为 令牌过期时间*2
HttpContext.Current.Cache.Insert("PASSPORT.TOKEN", dt, null, DateTime.MaxValue, TimeSpan.FromMinutes(double.Parse(System.Configuration.ConfigurationManager.AppSettings["Timeout"]) * 2));
}
}
分站凭证
分站凭证主要用于减少重复验证时网络的交互,比如用户已在分站a上登录过,当他再次访问分站a时,就不必使用令牌去主站验证了,因为分站a已有该用户的凭证。
分站凭证相对比较简单,使用Session、Cookie均可。
分站SSO页面基类
分站使用SSO的页面会做一系列的逻辑判断处理,如<图2>所示。如果为每个页面写一遍这样的逻辑会非常繁琐。OK,那么把这套逻辑封装成一个基类,凡是要使用SSO的页面继承该基类即可。如下代码所示:
public class AuthBase : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
if (Session["A.Cert"] != null)
{
//分站凭证存在
Response.Write("恭喜,分站凭证存在,您被授权访问该页面!");
}
else
{
//令牌验证结果返回
if (Request.QueryString["token"] != null)
{
//持有令牌
if (Request.QueryString["token"] != "$token$")
{
string tokenValue = Request.QueryString["token"];
//调用WebService获取主站凭证
//防止令牌伪造
//此处还可使用公钥私钥的非对称加密策略
SSO.SiteA.ServiceReference1.PassportServiceSoapClient passportService = new SSO.SiteA.ServiceReference1.PassportServiceSoapClient();
object cert = passportService.TokenGetCert(tokenValue);
if (cert != null)
{
//令牌正确
Session["A.Cert"] = cert;
Response.Write("恭喜,令牌存在,您被授权访问该页面!");
}
else
{
//令牌错误,去Passport登录
Response.Redirect(SSO.Common.Tools.TokenReplace());
}
}
//未持有令牌,去Passport登录
else
{
Response.Redirect(SSO.Common.Tools.TokenReplace());
}
}
//未进行令牌验证,去Passport验证
else
{
//当前url附加上token参数
Response.Redirect(SSO.Common.Tools.TokenUrl());
}
} base.OnLoad(e);
} }//end class
用户退出
<图3>
用户退出时分别清空主站令牌/凭证与所有分站凭证。DEMO中通过调用WebService清空该用户的主站令牌/凭证,通过iframe清空各分站凭证,请参阅DEMO中的详细代码实现。
主站过期令牌/凭证清除
读者可自行实现该逻辑,定时清除(DataTable)Cache[“PASSPORT.TOKEN”]中timeout字段超过当前时间的记录。
DEMO
DEMO开发环境
.Net Framework 4.0
Visual Studio 2012
在IIS中配置站点
配置4个站点指向相应的目录,并分别指定4个站点的主机头:
修改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/
DEMO下载
http://files.cnblogs.com/files/tinya/wujian_sso.rar
Asp.net单点登录解决方案的更多相关文章
- asp.net单点登录(SSO)解决方案
前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助.SSO的解决方案很多,但搜索结果令人大失所 ...
- SSO单点登录解决方案[转载]
1 什么是单点登陆 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互 ...
- .NET 单点登录解决方案
这里指的单点,泛指在WEB服务端,一个账户同一时刻只能存在一个票据! 大家开发中可能都碰到的一个问题,怎么使同一个用户,在同一时间内只允许登录一次. 很多人都会想到在数据库中用一个标识字段,登录进去置 ...
- SSO 单点登录解决方案
转自:http://www.blogjava.net/Jack2007/archive/2014/03/11/191795.html 1 什么是单点登陆 单点登录(Single Sign O ...
- 著名ERP厂商的SSO单点登录解决方案介绍一
SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...
- ASP.NET单点登录(代码)
[p=25, null, left]由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录.在ASP.NET中实现单点登录其实很简单,下面就把主要的方法和全部 ...
- sso单点登录解决方案收集
本文来自:http://blog.csdn.net/huwei2003/article/details/6038017 我的想法是使用集中验证方式,多个站点集中Passport验证. 主站:Passp ...
- 【分布式系列】session跨域及单点登录解决方案
Cookie机制 Cookie技术是客户端的解决方案,Cookie就是由服务器发给客户端的特殊信息,而这些信息以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息. ...
- Asp.Net_单点登录
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
随机推荐
- 数据分析--降维--LDA和PCA
一.因子分析 因子分析是将具有错综复杂关系的变量(或样本)综合为少数几个因子,以再现原始变量和因子之间的相互关系,探讨多个能够直接测量,并且具有一定相关性的实测指标是如何受少数几个内在的独立因子所支配 ...
- px、pt和em的区别
(转载)http://www.1z1b.com/one-blog-a-week/px-em-pt/ 这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网 ...
- 在Struts2标签s:textfield中显示正确的日期
Java代码 struts2中的日期期输入显示问题 struts2 中的默认的日期输出并不符合我们的中文日常习惯.以下是我知道的在struts2中进行日期格式化输出的几种方式. 1.利用 &l ...
- Hdfs数据备份
Hdfs数据备份 一.概述 本文的hdfs数据备份是在两个集群之间进行的,如果使用snapshot在同一个集群上做备份,如果datanode损坏或误操作清空了数据,这样的备份就无法完全保证数据安全性. ...
- Kaggle(一):房价预测
Kaggle(一) 房价预测 (随机森林.岭回归.集成学习) 项目介绍:通过79个解释变量描述爱荷华州艾姆斯的住宅的各个方面,然后通过这些变量训练模型, 来预测房价. kaggle项目链接:ht ...
- [转] Lodop、C-Lodop使用说明及样例
本文转自:http://www.lodop.net/LodopDemo.html Lodop(标音:劳道谱,俗称:露肚皮)是专业WEB控件,用它既可裁剪输出页面内容,又可用程序代码直接实现 复杂打印. ...
- mui 百度语音识别转换文字
前言 用mui混合开发的APP,现有一个功能需求就是语音转换成文字,并把语音进行保存.对此考虑两种选择讯飞和百度.最终选择了百度语音. 百度语音 通过官方文档我们大致可以确定如果想要实现语音识别,要做 ...
- 使用C#利用cmd来调用java jar包获取其中的数据
其实也很简单,就是在C#中构建一个Process,启动jar包,并且给jar包传递参数 因为我并没有怎么学过JAVA,所以只写了个很小的Demo,就是根据传入的参数获取对应的数据 以下是JAVA De ...
- [javaSE] 数组(查找-二分查找)
前提数组必须是有序的 定义最小,最大,中间的角标索引 int min,max,mid; min=0; max=arr.length-1; mid=(min+max)/2; 上面的索引需要变化,使用循环 ...
- CALayer及其子类
前言:这个系列要更新Core Animation的内容,但是CALayer是Core Animation的基础. 一 CALayer是什么? 摘自官网的一句话-Layers Provide the B ...