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 ...
随机推荐
- RR和RC复合语句加锁
mysql版本:5.7 RR复合语句: insert/update/delete+select,+号左边是影响数据的排他锁,+号右边是查询(当前读,其实相当于lock in share mode)到数 ...
- 关于gcc编译器中函数不用进行原型声明的解释
经过大量实验和参考网上的说法得出一个结论: gcc编译器中,函数可以不用提前进行原型声明,编译器会把函数调用同时认为是声明.需要注意的是,由于函数调用的时候并没有写明函数返回值,这是gcc把调用当成声 ...
- ruby字符串连接
malls = Mall.allcount = 0malls.each do |mall| count += 1 if mall.parent_ids[0] province ...
- Node.js数据流Stream之Duplex流和Transform流
Duplex流一个很好的例子是TCP套接字连接.需要实现_read(size)和_Write(data,encoding,callback)方法. var stream = require('stre ...
- WCF webHttpBinding协议上传接收文件
一般情况下wcf用webHttpBinding协议最多的场景就是前后端Json交互,会比较轻量级. 接收上传的文件也可以,不过要自己解析处理. 前端HTML很简单: <input type=&q ...
- tomcat服务器访问网址组成
运行tomcat服务器,其他设备访问的网址组成为: http://内网IP:端口/项目名字/网页名字.jsp
- 湘潭校赛 Easy Wuxing
Easy Wuxing Accepted : 25 Submit : 124 Time Limit : 1000 MS Memory Limit : 65536 KB 题目描述 “五行”是中国 ...
- [选译]MySQL5.7以上Zip版官方安装文档
前言 在windows上安装Zip版MySQL(选译) 学习mysql的朋友们会发现5.7+版本的mysql变得比以前难安装了许多(当然我们可以选择installer版本,但是这样总感觉对学习mysq ...
- wamp 安装monggo扩展
1.下载对应的monggo扩展 http://pecl.php.net/package/mongo 2. 找对应的版本 放在D:\program\wamp\bin\php\php5.5.12\ext ...
- git常用命令和场景
总结: git init //初始化本地git环境 git clone XXX//克隆一份代码到本地仓库 git pull //把远程库的代码更新到工作台 git pull --rebase orig ...