SSO 单点登录简单实现

1.知识点

  1. 单点登录: 简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.
  2. Redis: 一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。

RedisHelper已发布在nuget 中,通过Install-Package WebFramework.Redis -Version 1.3.0安装引用.
redis 界面工具: redis deskto
调用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1.	配置config文件:
<connectionStrings>
//redis 服务器
<add name="RedisConnectionString" connectionString="ipaddress:6379" />
</connectionStrings>
<appSettings>
//key前缀 可以不设置
<add key="DefaultKey" value="SSO_" />
</appSettings>

2. 实现:
var redis = new RedisHelper(1);
redis.StringSet("key", "asda"); //设置key-value
var stringre = redis.StringGet("key");
redis.HashSet("hashkey1", "fild1", new UserInfo { DisplayName = "贴,", NetId = "asd", DateTime = DateTime.Now });//hash 设置值
var h1 = redis.HashSetAsync<UserInfo>("hashkey2", "fild2", new UserInfo { DisplayName = "张,", NetId = "asd", DateTime = DateTime.Now });//异步取值

2.原理

名词解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1.	配置webconfig:
<!--服务端凭证过期时间(分钟)-->
<add key="CacheTimeOut" value="60" />
<!--登录地址-->
<add key="SSOurl" value="http://localhost:49694"/>
2. Push ,在子站点后添加web Reference: TicketService.asmx
3. 目前在code behind 代码中,需要在授权页面使用如下代码实现单点登录
Token.TicketService Ts = new Token.TicketService();
//无Token 验证
if (Request.QueryString["Token"] == null)
Response.Redirect(Ts.GetTokenUrl(Request.Url.AbsoluteUri));
if (Request.QueryString["Token"] == "$Token$")
Response.Redirect(Ts.ReplaceUrl(Request.Url.AbsoluteUri));
string tokenValue = Request.QueryString["Token"];
var userInfo = Ts.GetUserInfoByToken(tokenValue);
if (userInfo != null)
{
Session["UserInfo"] = new UserInfo { UserId = userInfo.NetId, UserName = userInfo.DisplayName, MailAddr = userInfo.MailAddress, mytasks = false, Token = tokenValue };
}
else
{
Response.Redirect(Ts.ReplaceUrl(Request.Url.AbsoluteUri));
}

子站点(www.a.com)访问:
(1) 无令牌,请求主站(account/default),通过User.Identity.IsAuthenticated 判断是否登录过(主站登录使用的是Form 表单登录),若登录过,则返回令牌. 否则返回子站点。
(2) 主站未登录过,重新请求主站登录页面(account/index),
登录成功后,生成令牌与对应的凭证,凭证信息中包含(本地cookie信息,用户信息),返回子站点并携带令牌。子站点通过令牌调用webservice 从redis服务器中获取用户数据(包含netid,displayname,mailaddress)
(3) 用户登出,清除cache,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
if (Session["UserInfo"] != null)
{
var sis = false;
Token.TicketService Ts = new Token.TicketService();
var userinfo = Session["UserInfo"] as UserInfo;
if (!string.IsNullOrEmpty(userinfo.Token))
{
sis = Ts.ClearToken(userinfo.Token);
Session["UserInfo"] = null;
Response.Redirect("ReportView.aspx");
}
}

源代码之后上传到github.
end.

坚持记录世界,分享世界