优化sso

This commit is contained in:
yubaolee 2016-11-17 19:48:12 +08:00
parent b3b0174430
commit 1a1ec43c57
14 changed files with 141 additions and 217 deletions

View File

@ -0,0 +1,16 @@
using System;
namespace Helper.Cache
{
[Serializable]
public class CacheObj<T>
{
public string key { get; set; }
public T Obj { get; set; }
public DateTime InvalidTime { get; set; }
public DateTime CreateTime { get; set; }
}
}

View File

@ -1,21 +1,24 @@
using System; using System;
using System.Globalization; using System.Globalization;
using Infrastructure.Cache;
namespace OpenAuth.App.SSO namespace Helper.Cache
{ {
public abstract class ServiceContext : IDisposable /// <summary>
/// 缓存工厂
/// <para>李玉宝新增于2016-11-09 9:42:52</para>
/// </summary>
public abstract class CacheProvider : IDisposable
{ {
/// <summary> /// <summary>
/// 缓存组件 /// 缓存组件
/// </summary> /// </summary>
public CacheContext CacheContext { get; private set; } public ICacheContext CacheContext { get; private set; }
/// <summary> /// <summary>
/// 动态设置缓存对象的新实例 /// 动态设置缓存对象的新实例
/// </summary> /// </summary>
/// <param name="cacheContext">缓存实例对象</param> /// <param name="cacheContext">缓存实例对象</param>
public void SetCacheInstance(CacheContext cacheContext) public void SetCacheInstance(ICacheContext cacheContext)
{ {
//先释放现有的缓存组件 //先释放现有的缓存组件
if (CacheContext != null) if (CacheContext != null)
@ -34,7 +37,7 @@ namespace OpenAuth.App.SSO
throw new ArgumentNullException("cacheContextType"); throw new ArgumentNullException("cacheContextType");
} }
if (!typeof(CacheContext).IsAssignableFrom(cacheContextType)) if (!typeof(ICacheContext).IsAssignableFrom(cacheContextType))
{ {
throw new ArgumentException( throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture, "该类型 {0} 必须继承自抽象类CacheContext", cacheContextType), string.Format(CultureInfo.CurrentCulture, "该类型 {0} 必须继承自抽象类CacheContext", cacheContextType),
@ -43,7 +46,7 @@ namespace OpenAuth.App.SSO
try try
{ {
CacheContext = Activator.CreateInstance(cacheContextType) as CacheContext; CacheContext = Activator.CreateInstance(cacheContextType) as ICacheContext;
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -13,9 +13,9 @@
using Enyim.Caching; using Enyim.Caching;
using Enyim.Caching.Memcached; using Enyim.Caching.Memcached;
namespace Infrastructure.Cache namespace Helper.Cache
{ {
public sealed class EnyimMemcachedContext : CacheContext public sealed class EnyimMemcachedContext : ICacheContext
{ {
private readonly MemcachedClient _memcachedClient = new MemcachedClient("memcached"); private readonly MemcachedClient _memcachedClient = new MemcachedClient("memcached");

View File

@ -1,21 +1,25 @@
// *********************************************************************** // ***********************************************************************
// Assembly : Infrastructure // Assembly : Helper
// Author : yubaolee // Author : Administrator
// Created : 06-21-2016 // Created : 09-21-2016
// //
// Last Modified By : yubaolee // Last Modified By : Administrator
// Last Modified On : 06-21-2016 // Last Modified On : 11-09-2016
// Contact : // Contact :
// File: EnyimMemcachedContext.cs // File: HttpApplicationContext.cs
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Web; using System.Web;
namespace Infrastructure.Cache namespace Helper.Cache
{ {
public sealed class SessionContext : CacheContext /// <summary>
/// 基于HttpApplication的存储
/// <para>李玉宝新增于2016-11-09 9:30:51</para>
/// </summary>
public sealed class HttpApplicationContext : ICacheContext
{ {
public override void Init() public override void Init()

View File

@ -1,48 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Cache
{
public interface ICache
{
/// <summary>
/// 加入缓存项
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
void Add(string key, object value, TimeSpan timeSpan);
/// <summary>
/// 加入依赖物理文件的缓存项
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="fullFileNameOfFileDependency">依赖的文件全路径</param>
void AddWithFileDependency(string key, object value, string fullFileNameOfFileDependency);
/// <summary>
/// 获取缓存项
/// </summary>
/// <param name="cacheKey"></param>
/// <returns></returns>
object Get(string cacheKey);
T Get<T>(string cacheKey) where T : class;
void Remove(string cacheKey);
/// <summary>
/// 如果不存在缓存项则添加,否则更新(相对过期)
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
void Set(string key, object value, TimeSpan timeSpan);
/// <summary>
/// 设置绝对过期时间
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
void SetAbsoluteExpiration(string key, object value, TimeSpan timeSpan);
}
}

View File

@ -1,11 +1,11 @@
using System; using System;
namespace Infrastructure.Cache namespace Helper.Cache
{ {
/// <summary> /// <summary>
/// 策略模式缓存组件,可实现动态插拔 /// 缓存接口
/// </summary> /// </summary>
public abstract class CacheContext : IDisposable public abstract class ICacheContext : IDisposable
{ {
/// <summary> /// <summary>
/// 初始化缓存组件 /// 初始化缓存组件

View File

@ -0,0 +1,65 @@
// ***********************************************************************
// Assembly : OpenAuth.WebApi
// Author : yubaolee
// Created : 07-11-2016
//
// Last Modified By : yubaolee
// Last Modified On : 07-11-2016
// Contact :
// File: CacheObjService.cs
// ***********************************************************************
using System;
namespace Helper.Cache
{
/// <summary>
/// 带超时结构的缓存
/// </summary>
public class ObjCacheProvider<T> : CacheProvider
{
public ObjCacheProvider()
{
SetCacheInstance(new HttpApplicationContext());
}
public bool Create(string key, T val)
{
var cacheobj = new CacheObj<T>
{
key = key,
InvalidTime = DateTime.Now.AddMinutes(5),
CreateTime = DateTime.Now,
Obj = val
};
//设置缓存
return CacheContext.Set(key, cacheobj);
}
/// <summary>
/// 根据失效时间获取缓存
/// <para>李玉宝于2016-11-08 16:54:04</para>
/// </summary>
/// <param name="key">The key.</param>
public T GetCache(string key)
{
var cache = CacheContext.Get<CacheObj<T>>(key);
if (cache == null) return default(T);
if (cache.InvalidTime > DateTime.Now)
{
return cache.Obj;
}
//移除无效Session缓存
Remove(key);
return default(T);
}
public void Remove(string key)
{
CacheContext.Remove(key);
}
}
}

View File

@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.Caching;
namespace Infrastructure.Cache
{
public class RuntimeMemoryCache : ICache
{
private readonly MemoryCache memoryCache = MemoryCache.Default;
/// <summary>
/// 加入缓存项(绝对过期时间)
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
public void Add(string key, object value, TimeSpan timeSpan)
{
if (!string.IsNullOrEmpty(key) && (value != null))
{
CacheItemPolicy cip = new CacheItemPolicy()
{
AbsoluteExpiration = DateTime.Now.Add(timeSpan)
};
this.memoryCache.Add(key, value, cip, null);
}
}
/// <summary>
/// 加入依赖物理文件的缓存项
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="fullFileNameOfFileDependency">依赖的文件全路径</param>
public void AddWithFileDependency(string key, object value, string fullFileNameOfFileDependency)
{
if (!string.IsNullOrEmpty(key) && (value != null))
{
CacheItemPolicy policy = new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.Now.AddMonths(1)
};
policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string> { fullFileNameOfFileDependency }));
this.memoryCache.Add(key, value, policy, null);
}
}
public object Get(string cacheKey)
{
return this.memoryCache[cacheKey];
}
public T Get<T>(string cacheKey) where T : class
{
object obj = this.Get(cacheKey);
if (obj != null)
{
return (obj as T);
}
return default(T);
}
public void Remove(string cacheKey)
{
this.memoryCache.Remove(cacheKey, null);
}
/// <summary>
/// 如果不存在缓存项则添加,否则更新(相对过期)
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
public void Set(string key, object value, TimeSpan timeSpan)
{
CacheItemPolicy cip = new CacheItemPolicy()
{
SlidingExpiration = timeSpan,
};
this.memoryCache.Set(key, value, cip, null);
}
/// <summary>
/// 设置绝对过期时间
/// </summary>
/// <param name="key">缓存项标识</param>
/// <param name="value">缓存项</param>
/// <param name="timeSpan">缓存失效时间</param>
public void SetAbsoluteExpiration(string key, object value, TimeSpan timeSpan)
{
CacheItemPolicy cip = new CacheItemPolicy()
{
AbsoluteExpiration = DateTime.Now.Add(timeSpan),
};
this.memoryCache.Set(key, value, cip, null);
}
}
}

View File

@ -80,11 +80,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AutoMapperExt.cs" /> <Compile Include="AutoMapperExt.cs" />
<Compile Include="Cache\CacheContext.cs" /> <Compile Include="Cache\CacheObj.cs" />
<Compile Include="Cache\CacheProvider.cs" />
<Compile Include="Cache\EnyimMemcachedContext.cs" /> <Compile Include="Cache\EnyimMemcachedContext.cs" />
<Compile Include="Cache\ICache.cs" /> <Compile Include="Cache\HttpApplicationContext.cs" />
<Compile Include="Cache\RuntimeMemoryCache.cs" /> <Compile Include="Cache\ICacheContext.cs" />
<Compile Include="Cache\SessionContext.cs" /> <Compile Include="Cache\ObjCacheProvider.cs" />
<Compile Include="CookieHelper.cs" /> <Compile Include="CookieHelper.cs" />
<Compile Include="DynamicLinq.cs" /> <Compile Include="DynamicLinq.cs" />
<Compile Include="DynamicQueryable.cs" /> <Compile Include="DynamicQueryable.cs" />

View File

@ -93,7 +93,6 @@
<Compile Include="SSO\AppInfoService.cs" /> <Compile Include="SSO\AppInfoService.cs" />
<Compile Include="SSO\AuthUtil.cs" /> <Compile Include="SSO\AuthUtil.cs" />
<Compile Include="SSO\PassportLoginRequest.cs" /> <Compile Include="SSO\PassportLoginRequest.cs" />
<Compile Include="SSO\ServiceContext.cs" />
<Compile Include="SSO\SSOAuthUtil.cs" /> <Compile Include="SSO\SSOAuthUtil.cs" />
<Compile Include="SSO\SSOController.cs" /> <Compile Include="SSO\SSOController.cs" />
<Compile Include="SSO\LoginResult.cs" /> <Compile Include="SSO\LoginResult.cs" />

View File

@ -1,9 +1,10 @@
using System; using System;
using System.Linq; using System.Linq;
using Helper.Cache;
namespace OpenAuth.App.SSO namespace OpenAuth.App.SSO
{ {
public class AppInfoService : ServiceContext public class AppInfoService : CacheProvider
{ {
public AppInfo Get(string appKey) public AppInfo Get(string appKey)
{ {

View File

@ -1,45 +1,42 @@
using System.Web; using System;
using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
namespace OpenAuth.App.SSO namespace OpenAuth.App.SSO
{ {
/// <summary>
/// 采用Attribute的方式验证登陆
/// <para>李玉宝新增于2016-11-09 10:08:10</para>
/// </summary>
public class SSOAuthAttribute : ActionFilterAttribute public class SSOAuthAttribute : ActionFilterAttribute
{ {
public const string Token = "Token"; public const string Token = "Token";
public const string SessionUserName = "SessionUserName";
public override void OnActionExecuting(ActionExecutingContext filterContext) public override void OnActionExecuting(ActionExecutingContext filterContext)
{ {
var token = ""; var token = "";
var cookieSessionUserName = "";
//Token by QueryString //Token by QueryString
var request = filterContext.HttpContext.Request; var request = filterContext.HttpContext.Request;
if (request.QueryString[Token] != null) if (request.QueryString[Token] != null)
{ {
token = request.QueryString[Token]; token = request.QueryString[Token];
filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(Token, token)); var cookie = new HttpCookie(Token, token)
{
Expires = DateTime.Now.AddDays(1)
};
filterContext.HttpContext.Response.Cookies.Add(cookie);
} }
else if (request.Cookies[Token] != null) //从Cookie读取Token else if (request.Cookies[Token] != null) //从Cookie读取Token
{ {
token = request.Cookies[Token].Value; token = request.Cookies[Token].Value;
} }
//SessionUserName by QueryString
if (request.QueryString[SessionUserName] != null)
{
cookieSessionUserName = request.QueryString[SessionUserName];
filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionUserName, cookieSessionUserName));
}
else if (request.Cookies[SessionUserName] != null) //从Cookie读取SessionUserName
{
cookieSessionUserName = request.Cookies[SessionUserName].Value;
}
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
{ {
//直接登录 //直接登录
filterContext.Result = LoginResult(cookieSessionUserName); filterContext.Result = LoginResult("");
return;
} }
else else
{ {
@ -47,21 +44,16 @@ namespace OpenAuth.App.SSO
if (AuthUtil.CheckLogin(token, request.RawUrl) == false) if (AuthUtil.CheckLogin(token, request.RawUrl) == false)
{ {
//会话丢失,跳转到登录页面 //会话丢失,跳转到登录页面
filterContext.Result = LoginResult(cookieSessionUserName); filterContext.Result = LoginResult("");
return;
} }
} }
base.OnActionExecuting(filterContext); base.OnActionExecuting(filterContext);
} }
private static ActionResult LoginResult(string username) public virtual ActionResult LoginResult(string username)
{ {
//跳转到SSO站点登陆
//return new RedirectResult(string.Format("{0}/sso/login?appkey={1}&username={2}",
// ConfigurationManager.AppSettings["SSOPassport"],
// ConfigurationManager.AppSettings["SSOAppKey"],
// username));
return new RedirectResult("/Login/Index"); return new RedirectResult("/Login/Index");
} }
} }

View File

@ -25,12 +25,10 @@ namespace OpenAuth.App.SSO
public class SSOController : Controller public class SSOController : Controller
{ {
public const string Token = "Token"; public const string Token = "Token";
public const string SessionUserName = "SessionUserName";
protected override void OnActionExecuting(ActionExecutingContext filterContext) protected override void OnActionExecuting(ActionExecutingContext filterContext)
{ {
var token = ""; var token = "";
var cookieSessionUserName = "";
//Token by QueryString //Token by QueryString
var request = filterContext.HttpContext.Request; var request = filterContext.HttpContext.Request;
@ -48,21 +46,10 @@ namespace OpenAuth.App.SSO
token = request.Cookies[Token].Value; token = request.Cookies[Token].Value;
} }
//SessionUserName by QueryString
if (request.QueryString[SessionUserName] != null)
{
cookieSessionUserName = request.QueryString[SessionUserName];
filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionUserName, cookieSessionUserName));
}
else if (request.Cookies[SessionUserName] != null) //从Cookie读取SessionUserName
{
cookieSessionUserName = request.Cookies[SessionUserName].Value;
}
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
{ {
//直接登录 //直接登录
filterContext.Result = LoginResult(cookieSessionUserName); filterContext.Result = LoginResult("");
return; return;
} }
else else
@ -71,7 +58,7 @@ namespace OpenAuth.App.SSO
if (AuthUtil.CheckLogin(token, request.RawUrl) == false) if (AuthUtil.CheckLogin(token, request.RawUrl) == false)
{ {
//会话丢失,跳转到登录页面 //会话丢失,跳转到登录页面
filterContext.Result = LoginResult(cookieSessionUserName); filterContext.Result = LoginResult("");
return; return;
} }
} }
@ -79,14 +66,8 @@ namespace OpenAuth.App.SSO
base.OnActionExecuting(filterContext); base.OnActionExecuting(filterContext);
} }
private static ActionResult LoginResult(string username) public virtual ActionResult LoginResult(string username)
{ {
//跳转到SSO站点登陆
//return new RedirectResult(string.Format("{0}/sso/login?appkey={1}&username={2}",
// ConfigurationManager.AppSettings["SSOPassport"],
// ConfigurationManager.AppSettings["SSOAppKey"],
// username));
return new RedirectResult("/Login/Index"); return new RedirectResult("/Login/Index");
} }
} }

View File

@ -10,7 +10,8 @@
// *********************************************************************** // ***********************************************************************
using System; using System;
using Infrastructure.Cache; using Helper.Cache;
using Infrastructure;
namespace OpenAuth.App.SSO namespace OpenAuth.App.SSO
{ {
@ -19,11 +20,11 @@ namespace OpenAuth.App.SSO
/// <para>测试环境用的是基于http application的SessionContext</para> /// <para>测试环境用的是基于http application的SessionContext</para>
/// <para>正式环境可以使用基于memcached的EnyimMemcachedContext</para> /// <para>正式环境可以使用基于memcached的EnyimMemcachedContext</para>
/// </summary> /// </summary>
public class UserAuthSessionService : ServiceContext public class UserAuthSessionService : CacheProvider
{ {
public UserAuthSessionService() public UserAuthSessionService()
{ {
SetCacheInstance(new SessionContext()); SetCacheInstance(new HttpApplicationContext());
} }
public bool Create(UserAuthSession model) public bool Create(UserAuthSession model)
@ -42,7 +43,9 @@ namespace OpenAuth.App.SSO
{ {
var cache = Get(token); var cache = Get(token);
if (cache == null) return false; if (cache == null) return false;
LogHelper.Log(token
+ "用户:" + cache.UserName
+ "登陆有效时间:" + cache.InvalidTime);
if (cache.InvalidTime > DateTime.Now) if (cache.InvalidTime > DateTime.Now)
{ {
//延长 //延长