新网 网站建立,手机网站建设推广,做360pc网站排名首页,查询网站死链接为什么80%的码农都做不了架构师#xff1f; 前些天一位朋友要我帮忙做一单点登录#xff0c;其实这个概念早已耳熟能详#xff0c;但实际应用很少#xff0c;难得最近轻闲#xff0c;于是决定通过本文来详细描述一个SSO解决方案#xff0c;希望对 大家有所… 为什么80%的码农都做不了架构师 前些天一位朋友要我帮忙做一单点登录其实这个概念早已耳熟能详但实际应用很少难得最近轻闲于是决定通过本文来详细描述一个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.Domainpassport.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); 主站凭证主站凭证是一个关系表包含了三个字段令牌、凭证数据、过期时间。有多种实现方式可供选择要求可靠的话用数据库要求性能的话用CacheDEMO中我使用的是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/// 授权页面基类/// /summarypublic 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/returnsprivate 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/returnsprivate 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