MVC - 单点登录中间件 (转)
http://www.cnblogs.com/wangrudong003/p/6435013.html
本章将要和大家分享的是一个单点登录中间件,中间件听起来高深其实这里只是吧单点登录要用到的逻辑和处理流程封装成了几个方法而已,默认支持采用redis服务保存session的方式,也可以使用参数Func<>方法来做自定义session存储操作的方式,就不用我默认提供的redis存储的方法了;要说本章内容的来源,其实是我在以前的ShenNiu.MVC管理系统中加入了最近做的调查问卷模块,这个问卷调查和ShenNiu.MVC不是一个站点,但是我的问卷调查系统可定在维护问卷或题目的时候需要登录人的信息,我又不想再单独弄一套账号方面的程序了,所以就采用这种单点登录模式,以此来提供调查问卷的所需要的用户信息,以及为了不久的将来自己写的某个模块也需要管理用户信息的话,就能省略掉用户模块了,不得不说单点登录在此刻发挥的作用之大;本章内容希望大家能够喜欢,也希望各位多多"扫码支持"和"推荐"谢谢!如果您想要和我们交流更多mvc相关信息可以来Ninesky框架作者:洞庭夕照 指定的官方群 428310563交流;
» 单点登录验证手画示例图
» ShenNiuApi.SDK封装中间件代码
» 调查问卷系统使用中间件示例
» 推广调查问卷系统
下面一步一个脚印的来分享:
» 单点登录验证手画示例图
首先,咋们要做一个简易的单点登录功能,需要明白其执行的流程和运作的原理,这里将图文并茂重点提出我认为关键的地方,先上一幅手工图:

看起来图画的不是很好看,不过我想表达的意思感觉还是表达清楚了;作为一个单点登录验证模块,最主要的流程有:
1. 未登录时:提供统一登录入口=》去数据库验证账号正确性=》存储会话session(这里采用redis存储token和用户登陆信息,利用其数据过期策略充当session会话机制)=》重定向到redirectUrl指定的地址
2. 已登录时:获取站点的cookie存储的sessionId(token)=》调用验证token有效接口=》这里有两种情况(a,b)
a) 有效token=》获取登录用户的session存储的信息(redis存储的value信息)
b) 无效token=》返回无效信息,构造登录入口地址
通过上面分析,大致的流程应该很明确了下面我们就来看封装的代码;
» ShenNiuApi.SDK封装中间件代码
这里要看的是中间件的3个方法:SsoMiddleWareServer(登录入口操作),SsoMiddleWareClient(Token验证及获取登录信息),SsoMiddleWareLoginOut(注销操作);这里我已经把方法打包放到了nuget上: Install-Package ShenNiuApi.SDK ,只需要下载最新的sdk,就能轻松帮您实现一个单点登录架构,下面来看具体的代码;
SsoMiddleWareServer(登录入口操作):

1 /// <summary>
2 /// 单点登录操作 SSOMiddleWare服务端(方法功能:
3 /// 1.生成sessionId
4 /// 2.存储session到redis(60分钟失效)或者自定义sessionStoreFunc方法中
5 /// 3.构造带有token的重定向地址)
6 /// 注:默认采用redis保存session,因此需要在conf中配置ReadAndWritePorts和OnlyReadPorts两个appSettings节点:
7 /// ReadAndWritePorts在conf中配置格式如:pwd@ip:port,多个使用‘|’隔开 实例:shenniubuxing3@127.0.0.1:6377
8 /// OnlyReadPorts在conf中配置格式如:pwd@ip:port,多个使用‘|’隔开 实例:shenniubuxing3@127.0.0.1:6377
9 /// </summary>
10 /// <typeparam name="TUserBaseInfo">存储登录信息的对象</typeparam>
11 /// <param name="userBaseInfo">登录信息</param>
12 /// <param name="redirectUrl">重定向地址(注:格式应为http://或者https://;并经过UrlEncode转码后的地址;如果是同站点下面的话无需http://标记)</param>
13 /// <param name="token">执行方法无误后ref返回唯一的token(注:token生成规则是唯一的tokenKey+guid+时间戳)</param>
14 /// <param name="tokenKey">生成token的Key(默认:666666)</param>
15 /// <param name="sessionStoreFun">自定义session存储方法(提供自定义操作保存session的方法,覆盖默认的reids存储方式)</param>
16 /// <param name="timeOut">60(分钟)</param>
17 /// <returns>追加有token的重定向地址</returns>
18 public string SsoMiddleWareServer<TUserBaseInfo>(TUserBaseInfo userBaseInfo, string redirectUrl, ref string token, string tokenKey = "666666", Func<TUserBaseInfo, bool> sessionStoreFun = null, int timeOut = 60)
19 where TUserBaseInfo : class,new()
20 {
21 var returnUrl = string.Empty;
22 try
23 {
24 //非空验证
25 if (string.IsNullOrWhiteSpace(redirectUrl) || userBaseInfo == null) { return returnUrl; }
26
27 //生成Token
28 token = Md5Extend.GetSidMd5Hash(tokenKey);
29
30 // ShenNiuApi默认的Redis存储session
31 if (sessionStoreFun == null && userBaseInfo != null)
32 {
33 if (!CacheRepository.Current(CacheType.RedisCache).SetCache<TUserBaseInfo>(token, userBaseInfo, timeOut, true)) { return returnUrl; }
34 }
35 else { if (!sessionStoreFun(userBaseInfo)) { return returnUrl; } }
36
37 //通域名站内系统登录
38 if (!Uri.IsWellFormedUriString(redirectUrl, UriKind.Absolute))
39 {
40 returnUrl = redirectUrl;
41 return returnUrl;
42 }
43
44 #region 解析并构造跳转链接
45 redirectUrl = HttpUtility.UrlDecode(redirectUrl);
46 redirectUrl = redirectUrl.TrimEnd('&');
47 redirectUrl = Regex.Replace(redirectUrl, "(&)?token=[^&]+(&)?", "");
48 Uri uri = new Uri(redirectUrl);
49 var queryStr = uri.Query;
50 redirectUrl += queryStr.Contains('?') ? "" : "?";
51 redirectUrl += string.IsNullOrWhiteSpace(queryStr.TrimStart('?')) ? "" : "&";
52 returnUrl = string.Format("{0}token={1}", redirectUrl, token);
53 #endregion
54 }
55 catch (Exception ex)
56 {
57 throw new Exception(ex.Message);
58 }
59 finally
60 {
61 if (string.IsNullOrWhiteSpace(returnUrl)) { token = string.Empty; }
62 }
63 return returnUrl;
64 }

SsoMiddleWareClient(Token验证及获取登录信息):

1 /// <summary>
2 /// 单点登录操作 SSOMiddleWare客户端(方法功能:
3 /// 1.验证客户端是否有sid或者url地址中带有最新的token
4 /// 2.获取服务端session的基本信息(注:默认直接读取服务端的redis库,同server方法一样需要配置对应的账号节点ReadAndWritePorts和OnlyReadPorts)
5 /// 3.重新设置客户端cookie有效期和服务端存储session的有效期)
6 /// </summary>
7 /// <typeparam name="TUserBaseInfo">登陆用户信息对象</typeparam>
8 /// <param name="httpContext">上下文HttpContext</param>
9 /// <param name="ssoLoginUrl">sso统一登陆入口地址</param>
10 /// <param name="redirectUrl">待重定向的地址</param>
11 /// <param name="userBaseInfo">获取的登陆用户信息</param>
12 /// <param name="token">唯一token(即:sid)</param>
13 /// <param name="getOrsetSessionFun">自定义获取服务端用户信息方法并且同时要满足重新设置新的session有效时间</param>
14 /// <param name="sidName">cookie保存的sid名称</param>
15 /// <param name="timeOut">过期时间</param>
16 /// <returns></returns>
17 public string SsoMiddleWareClient<TUserBaseInfo>(HttpContext httpContext, string ssoLoginUrl, string redirectUrl, ref TUserBaseInfo userBaseInfo, ref string token, Func<string, int, TUserBaseInfo> getAndsetSessionFun = null, string sidName = "sid", int timeOut = 60)
18 where TUserBaseInfo : class,new()
19 {
20 var returnUrl = string.Empty;
21 try
22 {
23 userBaseInfo = default(TUserBaseInfo);
24 token = string.Empty;
25 if (string.IsNullOrWhiteSpace(ssoLoginUrl) || string.IsNullOrWhiteSpace(redirectUrl) || string.IsNullOrWhiteSpace(sidName)) { return returnUrl; }
26
27 //设置过期后验证url串
28 returnUrl = string.Format("{0}?returnUrl={1}", ssoLoginUrl, HttpUtility.UrlEncode(redirectUrl));
29
30 //获取token
31 var cookie = httpContext.Request.Cookies.Get(sidName);
32 token = httpContext.Request.Params["token"];
33 token = string.IsNullOrWhiteSpace(token) ? (cookie == null ? "" : cookie.Value) : token;
34 if (string.IsNullOrWhiteSpace(token)) { return returnUrl; }
35
36 //获取用户基本信息
37 if (getAndsetSessionFun != null)
38 {
39 userBaseInfo = getAndsetSessionFun(token, timeOut);
40 }
41 else
42 {
43 userBaseInfo = CacheRepository.Current(CacheType.RedisCache).GetCache<TUserBaseInfo>(token, true);
44 }
45 if (userBaseInfo == null)
46 {
47 //过期cookie,清空
48 if (cookie != null)
49 {
50 cookie.Expires = DateTime.Now.AddDays(-1);
51 httpContext.Response.SetCookie(cookie);
52 }
53 return returnUrl;
54 }
55
56 //cookie被清除,需要重新设置
57 if (cookie == null)
58 {
59 cookie = new HttpCookie(sidName, token);
60 cookie.Expires = DateTime.Now.AddMinutes(timeOut);
61 httpContext.Response.AppendCookie(cookie);
62 }
63 else
64 {
65 //登陆验证都成功后,需要重新设置cookie中的toke失效时间
66 cookie.Value = token;
67 cookie.Expires = DateTime.Now.AddMinutes(timeOut);
68 httpContext.Response.SetCookie(cookie);
69 }
70
71 //设置服务端session的失效时间
72 if (getAndsetSessionFun == null)
73 {
74 CacheRepository.Current(CacheType.RedisCache).AddExpire(token, timeOut);
75 }
76 returnUrl = string.Empty;
77 }
78 catch (Exception ex)
79 {
80 throw new Exception(ex.Message);
81 }
82 finally { if (!string.IsNullOrWhiteSpace(returnUrl)) { token = string.Empty; } }
83 return returnUrl;
84 }

SsoMiddleWareLoginOut(注销操作):

1 /// <summary>
2 /// 单点登录操作 SSOMiddleWare 退出登陆
3 /// </summary>
4 /// <param name="httpContext">Http向下文</param>
5 /// <param name="removeSession">自定义移除方法</param>
6 /// <param name="sidName">cookie保存的sid名称</param>
7 /// <returns>true或false</returns>
8 public bool SsoMiddleWareLoginOut(HttpContext httpContext, Func<string, bool> removeSession = null, string sidName = "sid")
9 {
10 var isfalse = true;
11 try
12 {
13 if (string.IsNullOrWhiteSpace(sidName)) { sidName = "sid"; }
14
15 //获取cookie中的token
16 var cookie = httpContext.Request.Cookies.Get(sidName);
17 if (cookie == null) { return isfalse; }
18
19 //设置过期cookie(先过期cookie)
20 var key = cookie.Value;
21 cookie.Expires = DateTime.Now.AddDays(-1);
22 httpContext.Response.SetCookie(cookie);
23
24 //移除session
25 if (removeSession != null)
26 {
27 isfalse = removeSession(key);
28 }
29 else
30 {
31 isfalse = CacheRepository.Current(CacheType.RedisCache).Remove(key);
32 }
33 }
34 catch (Exception ex)
35 {
36
37 throw new Exception(ex.Message);
38 }
39 return isfalse;
40 }

每个方法的参数及作用,每行逻辑代码的都有注释,各位不妨研读下;这里要说的是每个方法都默认有操作redis存储session的步骤,因此能够看出此中间件默认采用的是redis服务存储session;
有人会问为什么会这样做,您单点登录难道最底层用的不是接口来操作登录或验证的吗?这里考虑有这样一个实用场景,作为一位中小型公司的员工来说,接触到服务器通常部署了整个公司的站点比如:站点1,站点2...尽管域名不一样但是都在同一台服务器上,再试想下如果用redis来存储session会话,此刻是不是就能认为我这台服务器就具有直接访问redis的读写权限(当然如果redis服务也在这台服务器上的话就更不用说了),那我直接在中间件中嵌入公共操作redis获取session,存储session等操作是不是都没问题,如此这般那我们还需要单独弄一个session(token)验证的api么,没必要的事情(对于单点登录站点和重定向站点而言没必要),因此我就这么干了,嵌入一个默认的redis操作哈哈(不服可以来辨);尽管如此不得不考虑更多的业务场景,万一登录账单和其他站点不在一个服务器(或者说无法直接访问redis呢),这里在3个中间件方法参数中提供了一个Func<>参数,每个方法的Func<>代表额意思有点差别,各位可以看下注释;有了这个自定义Func,中间件就能识别如果客户端有传递此方法,那么以Func为主,没有就采用默认的方式操作redis,这样允许使用者自定义方法扩展了使用者自己认为调用token验证的api或者其他合理的方式,这也保证了方法的通用性。
» 调查问卷系统使用中间件示例
下面我将使用真实的实例来使用ShenNiuApi.SDK中的中间件方法,这里例子是在我调查问卷系统中如何使用;首先通过nuget下载 Install-Package ShenNiuApi.SDK 最新的sdk,然后需要在做登录验证的Filter中或者继承Controller的父类中(我这里是后者)添加如下代码:

1 public class BaseController : Controller
2 {
3
4 protected StageModel.MoUserData _userData;
5
6 protected override void OnActionExecuting(ActionExecutingContext filterContext)
7 {
8
9 #region 采用ShenNiuApiClient的SsoClient中间件
10
11 ShenNiuApi.SDK.ShenNiuApiClient client = new ShenNiuApi.SDK.ShenNiuApiClient();
12
13 var ssoLogin="http://www.lovexins.com:8081/User/Login";
14 var redirectUrl = filterContext.HttpContext.Request.Url.AbsoluteUri;
15 var token = string.Empty;
16 var returnUrl = client.SsoMiddleWareClient<StageModel.MoUserData>(System.Web.HttpContext.Current, ssoLogin, redirectUrl, ref this._userData, ref token);
17 if (string.IsNullOrWhiteSpace(token) )
18 {
19 filterContext.Result = new RedirectResult(returnUrl);
20 return;
21 }
22 #endregion
23 }
24
25 protected void ShowMsg(string msg)
26 {
27
28 ModelState.AddModelError(string.Empty, msg);
29 }
30 }

只需要一句 client.SsoMiddleWareClient<StageModel.MoUserData>(System.Web.HttpContext.Current, ssoLogin, redirectUrl, ref this._userData, ref token); 即可完成问卷系统单点登录的验证和获取登录用户的信息,各种解析和设置sid的cookie信息都已经在中间件方法中完成了,是不是极大减少了您的编码量;为了对比下面我直接贴出没有使用SsoMiddleWareClient方法时候的代码量:
1 protected override void OnActionExecuting(ActionExecutingContext filterContext)
2 {
3
4
5 var returnUrl = filterContext.HttpContext.Request.Url.AbsoluteUri;
6 returnUrl = HttpUtility.UrlEncode(returnUrl);
7 // var result = new RedirectResult(string.Format("http://www.lovexins.com:8081/User/Login?returnUrl={0}", returnUrl));
8 var result = new RedirectResult(string.Format("http://172.16.9.6:4040/User/Login?returnUrl={0}", returnUrl));
9 var key = "Sid";
10 var timeOut = 30;
11 try
12 {
13 var cookie = filterContext.HttpContext.Request.Cookies.Get(key);
14 var token = filterContext.HttpContext.Request.Params["token"];
15 token = string.IsNullOrWhiteSpace(token) ? (cookie == null ? "" : cookie.Value) : token;
16 if (string.IsNullOrWhiteSpace(token))
17 {
18 filterContext.Result = result;
19 return;
20 }
21
22 this._userData = CacheRepository.Current(CacheType.RedisCache).GetCache<StageModel.MoUserData>(token, true);
23 if (this._userData == null && cookie != null)
24 {
25 //清空cookie
26 cookie.Expires = DateTime.Now.AddDays(-1);
27 filterContext.HttpContext.Response.SetCookie(cookie);
28 filterContext.Result = result;
29 return;
30 }
31 else if (this._userData == null)
32 {
33 filterContext.Result = result;
34 return;
35 }
36
37 if (cookie == null)
38 {
39 cookie = new HttpCookie(key, token);
40 cookie.Expires = DateTime.Now.AddMinutes(timeOut);
41 filterContext.HttpContext.Response.AppendCookie(cookie);
42 }
43 else
44 {
45 cookie.Value = token;
46 //登陆验证都成功后,需要重新设置cookie中的toke失效时间
47 cookie.Expires = DateTime.Now.AddMinutes(timeOut);
48 filterContext.HttpContext.Response.SetCookie(cookie);
49 }
50
51 //设置session失效时间
52 CacheRepository.Current(CacheType.RedisCache).AddExpire(token, timeOut);
53 }
54 catch (Exception ex)
55 {
56 filterContext.Result = result;
57 return;
58 }
59 }
从代码量看前者简单多了,有人会说了您这不就是弄了一个方法而已嘛,说什么代码量少了哈哈;这不得不说通常咋们哎使用第三方的插件或者类库,这样极大减少了咋们工作量和提升了开发速度的好处,有了ShenNiuApi.SDK您还需要担心什么呢;不过研究里面的具体步骤,逻辑代码我嘶吼非常赞成的;
有了在调查问卷的自定义Controller父类后,咋们还需要有一个登录的地方,这里我新创建的项目Stage.Web,在其登录get请求的Action中增加了如下代码:

1 #region 采用ShenNiuApiClient的SsoClient中间件
2
3 ShenNiuApi.SDK.ShenNiuApiClient client = new ShenNiuApi.SDK.ShenNiuApiClient();
4 var ssoLogin = loginUrl;
5 var redirectUrl = context.Request.Path;
6
7 var token = string.Empty;
8 t = default(T);
9 var returnUrl = client.SsoMiddleWareClient<T>(System.Web.HttpContext.Current, ssoLogin, redirectUrl, ref t, ref token, sidName: UserLoginExtend.CookieName);
10 if (string.IsNullOrWhiteSpace(token))
11 {
12 return new RedirectResult(returnUrl);
13 }
14 return null;
15 #endregion

直接通过中间件提供的 SsoMiddleWareClient 方法获取登录的token并验证是否已经登陆过,如果登录过了直接通过 return new RedirectResult(returnUrl); 重定向到returnUrl的地址中去;如果没有那么进入登录界面,录入账号信息后:

提交登录,进入咋们post的Action中进过数据库对账号匹配成功了,然后直接调用中间件方法来存储session并提供唯一的token值,再进行重定向跳转:

1 #region 采用ShenNiuApiClient的SsoServer中间件
2
3 ShenNiuApi.SDK.ShenNiuApiClient client = new ShenNiuApi.SDK.ShenNiuApiClient();
4
5 var timeOut = 60; //分钟
6 var token = string.Empty;
7 var redirectUrl = client.SsoMiddleWareServer<StageModel.MoUserData>(userData, returnUrl, ref token, timeOut: timeOut);
8 sbLog.AppendFormat("redirectUrl:{0},token:{1},", redirectUrl, token);
9 if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(redirectUrl))
10 {
11 //登陆失败
12 sbLog.Append("登陆失败,");
13 }
14 else
15 {
16 //写入Sso统一登陆站点的sid到cookie
17 var cookie = new HttpCookie(UserLoginExtend.CookieName, token);
18 cookie.Expires = DateTime.Now.AddMinutes(timeOut);
19 cookie.Domain = Request.Url.Host;
20 HttpContext.Response.AppendCookie(cookie);
21 }
22 var isAddLog = await StageClass._WrigLogAsync(sbLog.ToString());
23 return new RedirectResult(string.Format("{0}", redirectUrl));
24 #endregion

到此出sso的代码基本完成了就这么简单,不过这里默认采用的是我嵌入的redis服务来存储session信息的,所以还需要配置一个redis相关账号密码等的节点,这里只需要您在 C:\Conf\ShenNiuApi.xml 磁盘下面增加如下名称的xml文件,文件内容也简单:

1 <ShenNiuApi>
2 <RedisCache>
3 <!--读写权限服务地址,多个使用'|'隔开(格式如:pwd@ip:port)-->
4 <UserName>shenniubuxing3@111.111.111.152:1111</UserName>
5 <!--只读权限服务地址,多个使用'|'隔开-->
6 <UserPwd>shenniubuxing3@111.111.111.152:1111|shenniubuxing3@127.0.0.1:6377</UserPwd>
7 <ApiUrl></ApiUrl>
8 <ApiKey></ApiKey>
9 </RedisCache>
10 </ShenNiuApi>

把内容里面的redis账号,密码,端口,地址改成您自己的就行了;因为是在C盘中所以您服务器的其他站点也能够访问,假如您默认使用redis的方式存储session,那么只需要按照上面步骤就能快速的搭建一个单点登录架构;这里我提供下调查问卷使用单点登录测试的地址:www.lovexins.com:1001/Subject 测试账号:shenniu003 密码:123123,注意登录界面的域名和问卷调查的域名一样,只是端口不一样而已,如果您要看效果可以在浏览器F12,然后如图操作:

能够看到这个sid就是地址栏中的token值,这就是咋们定义的sessionId拉,您不想试试吗。
» 推广调查问卷系统
调查问卷我想很多公司都会用到,大家一般都会自己做一套,我这里要为大家推荐的是神牛问卷,具体怎么试用呢,可以登录地址http://www.lovexins.com:8081/User/Login 账号:shenniiu003 密码:123123,进入系统后直接点击“问卷管理”=>"调查问卷",在这里您就可以添加您想调查的问卷信息和选项:

如果您添加完成问卷信息后,可以直接点击“阅览”查看您的问卷展示内容和方式(支持移动手机浏览访问),这也是填写调查问卷的人看到的界面,目前支持的题目类型有(单选,多选,文本输入),测试地址:http://www.lovexins.com:1001/shenniu003/wenjuan7,地址中的shenniu003是根据账号来显示的,如果您是某个企业的hr或者老板这里地址栏可以直接注册成您公司的拼音名称或者汉字(是不是感觉还可以呢):

关键点来了,有了填写的用户咋们需要分析并做统计,这个时候只需要您点击问卷列表中的"统计",就能看到如下名目的图表:

您可以点击某一个问题选项对应的“红色”条,直接进入用户选项的分析报表:

看起来效果还是比较不错的吧,关键有数据统计给老板或者其他朋友看的时候,让人感觉“高大上”,这是选项样式的统计图,那么如果是用户填写类的统计呢,是如下这样的列表:

特点:
1. 富含单选,多选,用户填写类的题目类型
2. 单点登录架构,能快速嵌入到其他系统中
3. 手机web也能访问调查问问卷,问答问题
4. 详细的报表统计
5. 专业的维护人员哈哈
说明:最后要说的是此调查问卷系统是为了方便需要用到此功能的朋友和企业,如果您觉得还可以想发一两个问卷调查内容,可以联系我并让我给您单独分配一个管理者账号,当然如果您是某个企业带头人也想长久使用此调查系统可以联系邮箱:841202396@qq.com,随便您发多少问卷只要符合法定内容;

MVC - 单点登录中间件 (转)的更多相关文章
- MVC - 单点登录中间件
本章将要和大家分享的是一个单点登录中间件,中间件听起来高深其实这里只是吧单点登录要用到的逻辑和处理流程封装成了几个方法而已,默认支持采用redis服务保存session的方式,也可以使用参数Func& ...
- C# 单点登录 MVC
实现sso系统的主要难点: 1:不能直接访问数据库,有安全隐患,而且还容易乱套. 2:多个系统需要进行单点登录,逻辑需要严谨,能支持N多系统.而不只是少数几个系统. 3:代码不能过于复杂,需要简洁,灵 ...
- 单点登录 .NET MVC
原文:单点登录 .NET MVC CAS 实现单点登录 .NET MVC 单点登录 Single Sign On,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应 ...
- cas 在.net 下的单点登录实现及 ,Net Mvc的接入
最近在研究单点登录,发现用的最广的就是cas了,查了下资料,发现有人写了详细的说明 地址:http://www.cnblogs.com/zhenyulu/archive/2013/01/22/2870 ...
- .NET Core2.0+MVC 用session,cookie实现的sso单点登录
博主刚接触.NET Core2.0,想做一个单点登录的demo,所以参考了一些资料,这里给上链接: 1.http://www.cnblogs.com/baibaomen/p/sso-sequence- ...
- .NET Core2.0+MVC 用Redis/Memory+cookie实现的sso单点登录
之前发布过使用session+cookie实现的单点登录,博主个人用的很不舒服,为什么呢,博主自己测试的时候,通过修改host的方法,在本机发布了三个站点,但是,经过测试,发现,三个站点使用的sess ...
- 实战:ADFS3.0单点登录系列-集成MVC
本文将讲解如何让MVC应用程序与ADFS集成,完成认证的过程. 目录: 实战:ADFS3.0单点登录系列-总览 实战:ADFS3.0单点登录系列-前置准备 实战:ADFS3.0单点登录系列-ADFS3 ...
- asp.net mvc 权限过滤和单点登录(禁止重复登录)
1.权限控制使用controller和 action来实现,权限方式有很多种,最近开发项目使用控制控制器方式实现代码如下 /// <summary> /// 用户权限控制 /// < ...
- CAS 实现单点登录 .NET MVC
单点登录 Single Sign On,简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 单点登录原理 ...
随机推荐
- shell脚本基础和grep文本处理工具企业应用3
文本处理工具: linux上文本处理三剑客 grep,egrep,fgrep:文本过滤工具(模式:pattern)工具 grep:默认支持的是基本正则表达式: ...
- 【ARC072 E】Alice in linear land
被智商题劝退,告辞 题意 有一个人在一条数轴的距离原点为 \(D\) 的位置,他可以执行 \(n\) 次操作,每次操作为给定一个整数 \(d_i\),这个人向原点的方向走 \(d_i\) 个单位,但如 ...
- spring boot 导出 jar 配置文件的问题
网上有很多关联映射及讲解,想要说的是 主要就是 classpath 加上的话 jar就可以找到了
- 为什么程序员一定要会用Google和Stack Overflow?
为什么程序员一定要会用Google和Stack Overflow? https://blog.csdn.net/u012207345/article/details/81139665 StackOve ...
- JQuery实现简单的服务器轮询效果
很多论坛都有进入后,弹出提示,说有多少封邮件没有看,或者是一个oa系统,进入后,提示有多少个任务没有做.每隔一段时间会提示一次,但是如何实现呢.其实,利用jquery的话,会比较简单,核心元素就是js ...
- [Git] How to revert one file changes from one commit
Many times we might changed one file which we don't intent to do... but it was too late, until we fo ...
- WCF错误:由于目标计算机积极拒绝,无法连接;127.0.0.1:3456
问题描述 最近Windows打完补丁,原来部署在本机的WCF无法连接:出现如下WCF错误:由于目标计算机积极拒绝,无法连接:127.0.0.1:3456 解决方案 检查一下本机的服务:NetTcpAc ...
- C# 计算小数
private void button2_Click(object sender, EventArgs e) { ; List<string> list = new List<str ...
- C# 多线程任务分配辅助类
1)首先实现一个多线程的辅助类,代码如下: public class ThreadMulti { public delegate void DelegateComplete(); public del ...
- java+大文件上传解决方案
众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...
