看这个方案之前,先说明下为什么要加入SSO,以防对大家产生不好的影响。我们产品使用传统winform+db服务+Db存储方式开发,一群老菜帮子开发,以传统的datatble做数据传递,很多年了未有变化。

然后我来了,感觉我这个老菜帮子都受不了这种开发,然后下定决心,作了一些封装,看起来有点像orm的感觉了,并决定加入嵌入bs页面,美化界面,并补充winform在图表功能方面的短板。

然后就造成了各BS模块分别嵌入到CS不同的页面中,并且各BS模块中有涉及到对业务的操作。很危险!因为在网页中可以直接打开各BS模块视图,无需登录,无需验证等。针对这种情况,SSO需求由此而来…

目标:

  1.BS模块统一使用单点登录,不能没有限制就使用业务系统

  2.CS端嵌入BS时自动模拟SSO,实现可以免登录使用页面

 

下文SSO科普是复制不知道谁的博文的,具体是谁忘了,在此说明下

SSO整体流程图:

 

SSO分为SSO-ServerSSO-Client两个部分,SSO-Client可以是多个的,即各个需要单点登录的client

SSO-Server

SSO-Server主要负责用户登录、注销、为SSO-Client分配token、验证token的工作。

SSO-Server分配Token

为SSO-Client分配Token的部分,在SSO-Client请求SSO受信页面的时候,检查SSO-Server是否登录,如果没有登录则跳转到SSO-Server的登录页面,如果已登录,则执行分配Token的代码,在分配完成以后将TokenID作为参数添加到returnUrl中,并跳转到returnUrl。

当完成Token分配之后,页面将带有Token的参数跳转到SSO-Client页面,并在SSO-Client的Cookie中添加Token值,在以后的每次请求中,SSO-Client通过调用SSO-Server的服务来验证Token的合法性。

ValidateToken用来验证TokenID的合法性,KeepToken用来保持Token不会过期。

SSO-Client通过调用Validate验证Token,并得到当前的登录用户信息。

SSO-Client

SSO-Client作为受信系统来存在的,它自己没有认证系统,只能通过SSO-Server来完成用户身份认证的工作。

当用户请求SSO-Client的受保护资源时,SSO-Client会首先是否有TokenID,如果存在TokenID,则调用SSO-Server的接口来验证这个TokenID是否合法;

验证成功以后将会返回SSOToken的实例,里面包含已登录的用户信息

科普后动手:

MVC.SSO.Service:MVC+Redis,MVC实现SSO-Server的所有功能,存储和时效使用Redis管理,并使用Redis共享Session

主要代码:

     /// <summary>
/// 验证是否包含该token,并返回信息
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
[HttpPost]
public string ValidateToken(string key)
{
//var token = TokensManager.GetToken(key); try
{
MyToken token = new MyToken();
token.ValidateToken = false; if (BoolValidateToken(key))
{
token.User = redis.StringGet<USERS>(key);
token.ValidateToken = true;
} return JsonConvert.SerializeObject(token);
}
catch (Exception ex)
{
throw new Exception("ValidateToken:" + ex.Message);
}
}      /// <summary>
/// 登录
/// </summary>
/// <param name="name"></param>
/// <param name="passWord"></param>
/// <param name="backUrl"></param>
/// <returns></returns>
[HttpPost]
public string Login(string name, string passWord, string backUrl)
{
try
{
MyMsg msg = new MyMsg();
//tokenKey
byte[] byts = System.Text.Encoding.Default.GetBytes(string.Format("{0},{1}", name, passWord));
var key = Convert.ToBase64String(byts);
//判断是否TokenIds是否已存在该用户,不存在则判断登录,添加到token
if (!BoolValidateToken(key))
{
var user = userBll.GetUser(name, passWord);
if (user == null)
{
msg.IsLogined = false;
msg.Msg = "用户名或密码错误,登录失败!";
}
msg.IsLogined = true;
//并添加到全局变量中
//TokensManager.AddToken(key, user);
Session["Token"] = key;
redis.StringSet<USERS>(key, user);
} Session["Token"] = key;
Response.Cookies.Add(new HttpCookie("cToken", key));
if (!string.IsNullOrEmpty(backUrl))
{
var url = backUrl + "?token=" + key;
//Response.Redirect(backUrl + "?token=" + key, true);//生成一个tokenId 发放到客户端
msg.BackUrl = url;
}
msg.Msg = "欢迎您:" + name;
return JsonConvert.SerializeObject(msg);
}
catch (Exception ex)
{
throw;
}
}

BS端MVC-Client集成方案

MVC集成SSO方式为添加过滤器,并在需要添加SSO验证的控制器上添加上该过滤器

主要代码:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext); try
{
bool isLogined = false;//登录标志
var cToken = filterContext.HttpContext.Request.Cookies["cToken"];
var token = filterContext.HttpContext.Request["token"];
var sessionKey = HttpContext.Current.Session["Token"];
if (token != null || sessionKey != null || cToken != null)
{//eWFuc2hpLGE=
token = token ?? sessionKey.ToString() ?? cToken.Value;
var data = new { key = token };
//如果token不为空则去服务验证token是否有效
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(data));
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpClient = new HttpClient();
var responseJson = httpClient.PostAsync(SSOURL + "/ValidateToken", httpContent)
.Result.Content.ReadAsStringAsync().Result;
var myToken = JsonConvert.DeserializeObject<JH_OEMR_Model.MyToken>(responseJson);
if (myToken.ValidateToken)
{
isLogined = true;
}
} if (!isLogined)
filterContext.HttpContext.Response.Redirect(SSOURL+"?backUrl=" + filterContext.HttpContext.Request.Url, true);
}
catch (Exception ex)
{
filterContext.HttpContext.Response.Write("aaaaa"+ex.Message.ToString());
throw;
}
}

CS端集成SSO:

CS端加载BS页面时,先判断是否模拟登录,如未登录,模拟登录,然后访问BS端网址带上token即可

主要代码:

private static void LoginSSO()
{
var data = new { name = UName, passWord = UPwd, backUrl = string.Empty };
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(data));
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var httpClient = new HttpClient();
var responseJson = httpClient.PostAsync(SSOURL+"/Login", httpContent)
.Result.Content.ReadAsStringAsync().Result;
var myToken = JsonConvert.DeserializeObject<MyMsg>(responseJson);
if (myToken.IsLogined)
{
IsLoginedSSO = true;
}
}

SSO集成方案[随笔]的更多相关文章

  1. qlikview 权限管理和sso集成

    简单总结一下 qlikview 权限管理和SSO集成的过程, 在集成qlikview报表过程中碰到了很多坑, 甚至官方文档也不准确.  如果你也有类似的需求, 可以参考一下本文.  需要说明的是, 本 ...

  2. 可跨域的单点登录(SSO)实现方案

    可跨域的单点登录(SSO)实现方案 SSO简介 定义: 传统的单站点登录访问授权机制是:登录成功后将用户信息保存在session中,sessionId保存在cookie中,每次访问需要登录访问的资源( ...

  3. Spring+Struts集成(方案一)

    SSH框架是现在非常流行的框架之一,本文接下来主要来对Spring和Struts的集成进行展示. 集成原理:在Action中取得BeanFactory,通过BeanFactory取得业务逻辑对象. 集 ...

  4. Jmeter+Ant+Jenkins持续集成方案改进

    关于Jmeter+Ant+Jenkins如何搭建持续集成环境,网上资料一大把,就不多说了,本文主要谈一下期间的问题及扩展该持续集成方案. 其实核心的流程不复杂,Jenkins管理构建项目,Ant配置脚 ...

  5. FineReport和泛微OA(Ecology)的单点登录集成方案

    最近出现了很多关于帆软报表和泛微OA的集成问题,均出现在“单点登录”上.直接也有相关的文章介绍一些FineReport和泛微集成的背景.价值等,以及FineReport和OA的深度集成的方案,但是并没 ...

  6. (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案二

    http://blog.csdn.net/yerenyuan_pku/article/details/52894958 前面我们已经集成了Spring4.2.5+Hibernate4.3.11+Str ...

  7. (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一

    http://blog.csdn.net/yerenyuan_pku/article/details/52888808 前面我们已经集成了Spring4.2.5+Hibernate4.3.11这两个框 ...

  8. 日志服务与SIEM(如Splunk)集成方案实战

    背景信息 目标 本文主要介绍如何让阿里云日志服务与您的SIEM方案(如Splunk)对接, 以便确保阿里云上的所有法规.审计.与其他相关日志能够导入到您的安全运维中心(SOC)中. 名词解释 LOG( ...

  9. CDC+ETL实现数据集成方案

    欢迎咨询,合作! weix:wonter 名词解释: CDC又称变更数据捕获(Change Data Capture),开启cdc的源表在插入INSERT.更新UPDATE和删除DELETE活动时会插 ...

随机推荐

  1. Eigen中的map

    Map类用于通过C++中普通的连续指针或者数组 (raw C/C++ arrays)来构造Eigen里的Matrix类,这就好比Eigen里的Matrix类的数据和raw C++array 共享了一片 ...

  2. 自学java坎坷之路——20155312张竞予

    20155312 2006-2007-2 <Java程序设计>第一周学习总结 教材学习内容总结 第一周并没有在课堂上对教材内容进行学习,学习内容概括如下 课程分数构成,其中包括课堂测验(每 ...

  3. 686. Repeated String Match

    方法一.算是暴力解法吧,拼一段找一下 static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); cl ...

  4. 2019.01.06 vijos lxhgww的奇思妙想(长链剖分)

    传送门 长链剖分模板题. 题意简述:允许O(nlogn)O(nlog_n)O(nlogn​)预处理,让你支持O(1)O(1)O(1)查找任意一个点的kkk级祖先. 思路:因为要O(1)O(1)O(1) ...

  5. AI学习经验总结

    我的人工智能学习之路-从无到有精进之路 https://blog.csdn.net/sinox2010p1/article/details/80467475 如何自学人工智能路径规划(附资源,百分百亲 ...

  6. c# 二维list排序和计时

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...

  7. excel的小bug

    http://muchong.com/html/201710/3913047.html Excel也有相同现象,试着计算:exp(-1.5^2),exp(0-1.5^2),exp(-(1.5)^2)看 ...

  8. java http大文件断点续传上传

    因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 效果: 上传中,显示进度,时间,百分比. 点击[Pause]暂停,点击[Resume]继续. 2,代码分析 项目进行了封装使用最简单的 ...

  9. 查看Redis集群主从对应关系工具

    工具的作用: 1)比"cluster nodes"更为直观的显示结果 2)指出落在同一个IP上的master 3)指出落在同一个IP上的master和slave对 运行效果图: 源 ...

  10. js基础学习笔记(一)

    * 在js编写过程中,尽量保持统一使用单引号 'XXXX': * 所有变量都要声明 var,避免全局函数调用的冲突: 1.1    输出内容 docment.write(‘aileLi’); 改变某I ...