This commit is contained in:
yubaolee 2016-08-30 15:30:06 +08:00
commit 26225ad305
17 changed files with 612 additions and 3 deletions

View File

@ -0,0 +1,20 @@
using System.Web;
namespace Infrastructure.Auth
{
public class CacheKey
{
public static string SessionName = "OpenAuth";
public static string UserSessionName = "Session_";
private static string GetSessionId()
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(SessionName);
string remoteBrowserIp = WebUtility.GetIP();
return UserSessionName + remoteBrowserIp + ":" + cookie.Value;
}
public static string UserID
{
get { return GetSessionId(); }
}
}
}

View File

@ -0,0 +1,79 @@
using Infrastructure.Cache;
using System;
using System.Web;
namespace Infrastructure.Auth
{
public class CacheSession
{
ICache cache = DIContainer.Resolve<ICache>();
private HttpContext context;
public CacheSession(bool IsReadOnly)
{
this.IsReadOnly = IsReadOnly;
}
public CacheSession(HttpContext context, bool IsReadOnly, TimeSpan TimeOut, ICache cacheService)
{
this.context = context;
this.IsReadOnly = IsReadOnly;
this.TimeOut = TimeOut;
}
public CacheSession(HttpContext context, bool IsReadOnly)
{
this.context = context;
this.IsReadOnly = IsReadOnly;
GetSessionId();
if (CacheKey.UserID != null)
{
var userInfo = cache.Get<dynamic>(CacheKey.UserID);
}
}
//获取会话是否已经验证通过
public bool IsAuthenticated
{
get
{
if (cache.Get(SessionId) == null)
{
return false;
}
else
{
return true;
}
}
}
//会话唯一Id
public string SessionId
{
get
{
return GetSessionId();
}
}
public static string SessionName = CacheKey.SessionName;
public static string UserSessionName = CacheKey.UserSessionName;
//指示会话是否为只读true为只读
public bool IsReadOnly { get; set; }
//超时期限
public TimeSpan TimeOut { get; set; }
private string GetSessionId()
{
HttpCookie cookie = context.Request.Cookies.Get(SessionName);
string remoteBrowserIp = WebUtility.GetIP();
if (cookie == null || string.IsNullOrEmpty(cookie.Value))
{
string newSessionId = Guid.NewGuid().ToString();
HttpCookie newCookie = new HttpCookie(SessionName, newSessionId);
newCookie.HttpOnly = IsReadOnly;
context.Response.Cookies.Add(newCookie);
return UserSessionName + remoteBrowserIp + ":" + newSessionId;
}
else
{
return UserSessionName + remoteBrowserIp + ":" + cookie.Value;
}
}
}
}

View File

@ -0,0 +1,48 @@
using Infrastructure.Cache;
using System;
using System.Web;
namespace Infrastructure.Auth
{
/// <summary>
/// 身份认证服务实现(缓存可分布式部署)
/// </summary>
public class FormsAuthenticationService : IAuthenticationService
{
ICache cacheService;
CacheSession cacheSession;
HttpContext httpContext = HttpContext.Current;
//hpf 缓存相关
public FormsAuthenticationService()
{
cacheService = DIContainer.Resolve<ICache>();
cacheSession = new CacheSession(httpContext, true);
}
/// <summary>
/// 获取当前认证的用户
/// </summary>
/// <returns>当前用户未通过认证则返回null</returns>
public dynamic GetAuthenticatedUser()
{
if (httpContext == null || !cacheSession.IsAuthenticated)
{
return null;//hpf未登录
}
return cacheService.Get<dynamic>(cacheSession.SessionId);
}
public void SignIn(string loginName, dynamic userInfo, TimeSpan expiration)
{
var sessionId = cacheSession.SessionId;
cacheService.Set(sessionId, userInfo, expiration);
}
public void SignOut()
{
if (!string.IsNullOrEmpty(CacheKey.UserID))
{
cacheService.Remove(CacheKey.UserID);
}
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Auth
{
/// <summary>
/// 用于身份认证接口
/// </summary>
public interface IAuthenticationService
{
/// <summary>
/// 登录
/// </summary>
/// <param name="loginName">登录名</param>
/// <param name="userData">与登录名相关的用户信息</param>
/// <param name="expiration">登录Cookie的过期时间单位分钟。</param>
void SignIn(string loginName, dynamic userInfo, TimeSpan expiration);
/// <summary>
/// 注销
/// </summary>
void SignOut();
/// <summary>
/// 获取当前登录的用户
/// </summary>
/// <returns>当前用户未通过认证则返回null</returns>
dynamic GetAuthenticatedUser();
}
}

View File

@ -0,0 +1,20 @@
namespace Infrastructure.Auth
{
/// <summary>
/// 当前登录用户相关
/// </summary>
public class UserContext
{
public static dynamic CurrentUser
{
get
{
IAuthenticationService authenticationService = DIContainer.ResolvePerHttpRequest<IAuthenticationService>();
var currentUser = authenticationService.GetAuthenticatedUser();
if (currentUser != null)
return currentUser;
return null;
}
}
}
}

View File

@ -0,0 +1,48 @@
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

@ -0,0 +1,93 @@
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

@ -0,0 +1,75 @@
using Autofac;
using Autofac.Core;
using System.Web.Mvc;
namespace Infrastructure
{
/// <summary>
/// 依赖注入
/// </summary>
public class DIContainer
{
private static IContainer iContainer;
public static void RegisterContainer(IContainer container)
{
iContainer = container;
}
/// <summary>
/// 按类型获取组件
/// </summary>
/// <typeparam name="Tservice"></typeparam>
/// <returns></returns>
public static Tservice Resolve<Tservice>()
{
return ResolutionExtensions.Resolve<Tservice>(iContainer);
}
/// <summary>
/// 按参数获取组件
/// </summary>
/// <typeparam name="Tservice"></typeparam>
/// <param name="paramters"></param>
/// <returns></returns>
public static Tservice Resolve<Tservice>(params Parameter[] parameters)
{
return ResolutionExtensions.Resolve<Tservice>(iContainer, parameters);
}
/// <summary>
/// 按key获取组件
/// </summary>
/// <typeparam name="Tservice">组件类型</typeparam>
/// <param name="serviceKey">枚举类型的key</param>
/// <returns>返回获取的组件</returns>
public static Tservice ResolveKeyed<Tservice>(object serviceKey)
{
return ResolutionExtensions.ResolveKeyed<Tservice>(iContainer, serviceKey);
}
/// <summary>
/// 按名称获取组件
/// </summary>
/// <typeparam name="Tservice"></typeparam>
/// <param name="serviceName"></param>
/// <returns></returns>
public static Tservice ResolveNamed<Tservice>(string serviceName)
{
return ResolutionExtensions.ResolveNamed<Tservice>(iContainer, serviceName);
}
/// <summary>
/// 获取InstancePerHttpRequest的组件 mvc
/// </summary>
/// <typeparam name="Tservice"></typeparam>
/// <returns></returns>
public static Tservice ResolvePerHttpRequest<Tservice>()
{
IDependencyResolver current = DependencyResolver.Current;
if (current != null)
{
Tservice service = (Tservice)current.GetService(typeof(Tservice));
if (service != null)
{
return service;
}
}
return ResolutionExtensions.Resolve<Tservice>(iContainer);
}
}
}

View File

@ -32,6 +32,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=3.5.0.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\packages\Autofac.3.5.2\lib\net40\Autofac.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="AutoMapper">
<HintPath>..\packages\AutoMapper.4.1.0\lib\net45\AutoMapper.dll</HintPath>
</Reference>
@ -58,7 +62,16 @@
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Caching" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@ -66,11 +79,19 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Auth\CacheKey.cs" />
<Compile Include="Auth\CacheSession.cs" />
<Compile Include="Auth\FormsAuthenticationService.cs" />
<Compile Include="Auth\IAuthenticationService.cs" />
<Compile Include="Auth\UserContext.cs" />
<Compile Include="AutoMapperExt.cs" />
<Compile Include="Cache\CacheContext.cs" />
<Compile Include="Cache\EnyimMemcachedContext.cs" />
<Compile Include="Cache\ICache.cs" />
<Compile Include="Cache\RuntimeMemoryCache.cs" />
<Compile Include="Cache\SessionContext.cs" />
<Compile Include="CookieHelper.cs" />
<Compile Include="DIContainer.cs" />
<Compile Include="DynamicLinq.cs" />
<Compile Include="DynamicQueryable.cs" />
<Compile Include="Filter.cs" />
@ -79,6 +100,11 @@
<Compile Include="JsonConverter.cs" />
<Compile Include="JsonHelper.cs" />
<Compile Include="LogHelper.cs" />
<Compile Include="MVC\AuthenticationAttribute.cs" />
<Compile Include="MVC\JsonExceptionAttribute.cs" />
<Compile Include="MVC\LogExceptionAttribute.cs" />
<Compile Include="MVC\NoFilterAttribute.cs" />
<Compile Include="MVC\UiResponse.cs" />
<Compile Include="ObjectHelper.cs" />
<Compile Include="PredicateBuilder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -86,6 +112,7 @@
<Compile Include="SessionHelper.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="UriUtil.cs" />
<Compile Include="WebUtility.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -0,0 +1,12 @@
using System.Web;
using System.Web.Mvc;
namespace Infrastructure.MVC
{
/// <summary>
/// 登录验证
/// </summary>
public class AuthenticationAttribute: AuthorizeAttribute
{
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Web.Mvc;
namespace Infrastructure.MVC
{
/// <summary>
/// 加入action级ajax请求发生500内部错误时返回给浏览器json提示
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class JsonExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled)
{
//返回异常json
filterContext.Result = new JsonResult
{
Data = new UiResponse { statusCode = "300", message = filterContext.Exception.Message }
};
}
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace Infrastructure.MVC
{
/// <summary>
/// 加入全局异常处理500内部错误
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class LogExceptionAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled)
{
string controllerName = filterContext.RouteData.Values["controller"].ToString();
string actionName = filterContext.RouteData.Values["action"].ToString();
string msgTemp = WebUtility.GetIP() + "在执行controller" + controllerName + "的" + actionName + "时产生异常:" + filterContext.Exception.Message;
//hpf此处写入异常日志
LogHelper.Fatal(msgTemp);
}
if (filterContext.Result is JsonResult)
{
filterContext.ExceptionHandled = true;//异常已处理
}
else
{
//通过base返回系统默认异常处理上向错误页面跳转
base.OnException(filterContext);
}
}
}
}

View File

@ -0,0 +1,10 @@
using System;
namespace Infrastructure.MVC
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class NoFilterAttribute : Attribute
{
public NoFilterAttribute() { }
}
}

View File

@ -0,0 +1,44 @@

namespace Infrastructure.MVC
{
/// <summary>
/// 前端框架ajax错误返回
/// </summary>
public class UiResponse
{
public string statusCode
{
get; set;
}
public string message
{
get; set;
}
public string tabid
{
get; set;
}
public bool closeCurrent
{
get; set;
}
public string forward { get; set; }
public string forwardConfirm { get; set; }
public UiResponse()
{
statusCode = "200";
message = "操作成功";
tabid = "";
closeCurrent = false;
forward = "";
forwardConfirm = "";
}
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Infrastructure
{
public static class WebUtility
{
/// <summary>
/// 获取IP地址
/// </summary>
/// <returns>返回获取的ip地址</returns>
public static string GetIP()
{
return GetIP(HttpContext.Current);
}
/// <summary>
/// 透过代理获取真实IP
/// </summary>
/// <param name="httpContext">HttpContext</param>
/// <returns>返回获取的ip地址</returns>
public static string GetIP(HttpContext httpContext)
{
string userHostAddress = string.Empty;
if (httpContext != null)
{
userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(userHostAddress))
{
userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
if (string.IsNullOrEmpty(userHostAddress))
{
userHostAddress = HttpContext.Current.Request.UserHostAddress;
}
}
return userHostAddress;
}
}
}

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net45" />
<package id="AutoMapper" version="4.1.0" targetFramework="net45" />
<package id="EnyimMemcached" version="2.12" targetFramework="net45" />
<package id="log4net" version="2.0.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

View File

@ -132,7 +132,7 @@
$('#bjui-container').height(iContentH)
$('#bjui-navtab').width(iContentW)
$('#bjui-leftside, #bjui-sidebar, #bjui-sidebar-s, #bjui-splitBar, #bjui-splitBarProxy').css({height:'100%'})
$('#bjui-navtab .tabsPageContent').height(iContentH - navtabH)
$('#bjui-navtab .tabsPageContent').height(iContentH - navtabH - 1)//下边框遮盖问题
/* fixed pageFooter */
setTimeout(function() {