/// <summary> /// 拦截服务请求 /// </summary> public override async Task <TResponse> UnaryServerHandler <TRequest, TResponse>(TRequest request, ServerCallContext context, UnaryServerMethod <TRequest, TResponse> continuation) { Endpoint endpoint = OwinContextReader.Current.GetEndpoint(); bool needAuthorize = AspNetSetting.Authorized; bool allowAnonymous = endpoint.Metadata.GetMetadata <AllowAnonymousAttribute>() != null; if (needAuthorize && !allowAnonymous) { string headerKey = SessionKey.PublicKey.ToLower(); Metadata.Entry headerEntry = context.RequestHeaders.Get(headerKey); string publicKey = headerEntry?.Value; if (string.IsNullOrWhiteSpace(publicKey)) { string message = "身份认证消息头不存在,请检查程序!"; NoPermissionException innerException = new NoPermissionException(message); Status status = new Status(StatusCode.Unauthenticated, message, innerException); throw new RpcException(status); } LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey); if (loginInfo == null) { string message = "身份过期,请重新登录!"; NoPermissionException innerException = new NoPermissionException(message); Status status = new Status(StatusCode.Unauthenticated, message, innerException); throw new RpcException(status); } //通过后,重新设置缓存过期时间 CacheMediator.Set(publicKey, loginInfo, DateTime.Now.AddMinutes(GlobalSetting.AuthenticationTimeout)); } return(await continuation.Invoke(request, context)); }
/// <summary> /// 接收请求后事件 /// </summary> /// <param name="request">请求消息</param> /// <param name="channel">信道</param> /// <param name="instanceContext">WCF实例上下文</param> public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { //获取消息头 MessageHeaders headers = request.Headers; string action = headers.Action; EndpointDispatcher endpointDispatcher = OperationContext.Current.EndpointDispatcher; DispatchOperation operationDispatcher = endpointDispatcher.DispatchRuntime.Operations.Single(x => x.Action == action); /* * 通过OperationBehavior设置Impersonation属性, * 默认值为ImpersonationOption.NotAllowed, * 当ImpersonationOption.NotAllowed时验证身份, * 如无需验证身份,则将Impersonation属性赋值为ImpersonationOption.Allowed。 */ if (operationDispatcher.Impersonation == ImpersonationOption.NotAllowed) { #region # 验证消息头 if (!headers.Any(x => x.Name == CommonConstants.WCFAuthenticationHeader && x.Namespace == GlobalSetting.ApplicationId)) { string message = "身份认证消息头不存在,请检查程序!"; NoPermissionException innerException = new NoPermissionException(message); FaultReason faultReason = new FaultReason(message); FaultCode faultCode = new FaultCode(HttpStatusCode.Unauthorized.ToString()); throw new FaultException <NoPermissionException>(innerException, faultReason, faultCode); } #endregion //读取消息头中的公钥 Guid publicKey = headers.GetHeader <Guid>(CommonConstants.WCFAuthenticationHeader, GlobalSetting.ApplicationId); //认证 lock (_Sync) { //以公钥为键,查询分布式缓存,如果有值则通过,无值则不通过 LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); if (loginInfo == null) { string message = "身份过期,请重新登录!"; NoPermissionException innerException = new NoPermissionException(message); FaultReason faultReason = new FaultReason(message); FaultCode faultCode = new FaultCode(HttpStatusCode.Unauthorized.ToString()); throw new FaultException <NoPermissionException>(innerException, faultReason, faultCode); } //通过后,重新设置缓存过期时间 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(GlobalSetting.AuthenticationTimeout)); } } return(null); }
/// <summary> /// 初始化信息系统 /// </summary> /// <param name="systemNo">信息系统编号</param> /// <param name="host">主机名称</param> /// <param name="port">端口</param> /// <param name="index">首页</param> public void InitInfoSystem(string systemNo, string host, int port, string index) { InfoSystem currentSystem = this._unitOfWork.Resolve <InfoSystem>(systemNo); currentSystem.Init(host, port, index); this._unitOfWork.RegisterSave(currentSystem); this._unitOfWork.Commit(); //清除缓存 CacheMediator.Remove(typeof(IInfoSystemRepository).FullName); }
/// <summary> /// 登录 /// </summary> /// <param name="loginId">登录名</param> /// <param name="password">密码</param> /// <returns>登录信息</returns> public LoginInfo Login(string loginId, string password) { //生成公钥 Guid publicKey = Guid.NewGuid(); //生成登录信息 LoginInfo loginInfo = new LoginInfo(loginId, CommonConstants.AdminLoginId, publicKey); //以公钥为键,登录信息为值,存入分布式缓存 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(20)); return(loginInfo); }
public void TestSetAndGetCache() { for (int index = 0; index < 1000; index++) { string cacheKey = Guid.NewGuid().ToString(); string cacheValue = Guid.NewGuid().ToString(); CacheMediator.Set(cacheKey, cacheValue); string value = CacheMediator.Get <string>(cacheKey); Assert.IsTrue(value == cacheValue); } }
public void TestSetAndGetCacheParallel() { Parallel.For(0, 1000, index => { string cacheKey = Guid.NewGuid().ToString(); string cacheValue = Guid.NewGuid().ToString(); CacheMediator.Set(cacheKey, cacheValue); string value = CacheMediator.Get <string>(cacheKey); Assert.IsTrue(value == cacheValue); }); }
//命令部分 #region # 创建信息系统 —— void CreateInfoSystem(string systemNo, string systemName... /// <summary> /// 创建信息系统 /// </summary> /// <param name="systemNo">组织编号</param> /// <param name="systemName">信息系统名称</param> /// <param name="adminLoginId">系统管理员登录名</param> /// <param name="applicationType">应用程序类型</param> public void CreateInfoSystem(string systemNo, string systemName, string adminLoginId, ApplicationType applicationType) { //验证 Assert.IsFalse(this._repMediator.UserRep.Exists(adminLoginId), $"登录名:\"{adminLoginId}\"已存在,请重试!"); InfoSystem infoSystem = new InfoSystem(systemNo, systemName, adminLoginId, applicationType); this._unitOfWork.RegisterAdd(infoSystem); this._unitOfWork.UnitedCommit(); //清除缓存 CacheMediator.Remove(typeof(IInfoSystemRepository).FullName); }
/// <summary> /// 获取登录信息 /// </summary> /// <returns>登录信息</returns> public LoginInfo GetLoginInfo() { HttpContext httpContext = OwinContextReader.Current; if (httpContext != null && httpContext.Request.Headers.TryGetValue(SessionKey.PublicKey, out StringValues header)) { Guid publicKey = new Guid(header.ToString()); LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); return(loginInfo); } return(null); }
public void TestRemoveCache() { string cacheKey = "key"; string cacheValue = "value"; CacheMediator.Set(cacheKey, cacheValue); //移除 CacheMediator.Remove(cacheKey); string value = CacheMediator.Get <string>(cacheKey); Assert.IsNull(value); }
/// <summary> /// 登录 /// </summary> /// <param name="loginId">登录名</param> /// <param name="password">密码</param> /// <param name="clientId">客户端Id</param> /// <returns>登录信息</returns> public LoginInfo Login(string loginId, string password, string clientId = null) { //生成公钥 Guid publicKey = Guid.NewGuid(); //生成登录信息 LoginInfo loginInfo = new LoginInfo(loginId, CommonConstants.AdminLoginId, publicKey); loginInfo.ClientId = NetworkExtension.GetLocalMacAddress(); //以公钥为键,登录信息为值,存入分布式缓存 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(20)); return(loginInfo); }
public void TestRemoveRangeCache_Keys() { string cacheKey1 = "key1"; string cacheKey2 = "key2"; string cacheValue1 = "value1"; string cacheValue2 = "value2"; CacheMediator.Set(cacheKey1, cacheValue1); CacheMediator.Set(cacheKey2, cacheValue2); //移除 CacheMediator.RemoveRange(new[] { cacheKey1, cacheKey2 }); Assert.IsFalse(CacheMediator.Exists(cacheKey1)); Assert.IsFalse(CacheMediator.Exists(cacheKey2)); }
//Implements #region # 执行授权过滤器事件 —— void OnAuthorization(AuthorizationFilterContext context) /// <summary> /// 执行授权过滤器事件 /// </summary> public void OnAuthorization(AuthorizationFilterContext context) { //判断是否是ApiController if (context.ActionDescriptor is ControllerActionDescriptor actionDescriptor && actionDescriptor.ControllerTypeInfo.IsDefined(typeof(ApiControllerAttribute), true)) { bool needAuthorize = AspNetSetting.Authorized; bool allowAnonymous = this.HasAttr <AllowAnonymousAttribute>(context.ActionDescriptor); if (needAuthorize && !allowAnonymous) { if (!context.HttpContext.Request.Headers.TryGetValue(SessionKey.PublicKey, out StringValues header)) { ObjectResult response = new ObjectResult("身份认证消息头不存在,请检查程序!") { StatusCode = (int)HttpStatusCode.Unauthorized }; context.Result = response; } else { //读取消息头中的公钥 Guid publicKey = new Guid(header.ToString()); //认证 lock (_Sync) { //以公钥为键,查询分布式缓存,如果有值则通过,无值则不通过 LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); if (loginInfo == null) { ObjectResult response = new ObjectResult("身份过期,请重新登录!") { StatusCode = (int)HttpStatusCode.Unauthorized }; context.Result = response; } else { //通过后,重新设置缓存过期时间 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(GlobalSetting.AuthenticationTimeout)); } } } } } }
//Private #region # 构造登录信息 —— LoginInfo BuildLoginInfo(User user... /// <summary> /// 构造登录信息 /// </summary> /// <param name="user">用户</param> /// <param name="clientId">客户端Id</param> /// <returns>登录信息</returns> private LoginInfo BuildLoginInfo(User user, string clientId) { //生成公钥 Guid publicKey = Guid.NewGuid(); //生成登录信息 LoginInfo loginInfo = new LoginInfo(user.Number, user.Name, publicKey); loginInfo.ClientId = clientId; #region # 登录信息的信息系统部分/菜单部分/权限部分 /*角色部分*/ ICollection <Guid> roleIds = user.GetRelatedRoleIds(); /*信息系统部分*/ IEnumerable <string> infoSystemNos = user.GetRelatedInfoSystemNos(); IDictionary <string, InfoSystem> infoSystems = this._repMediator.InfoSystemRep.Find(infoSystemNos); loginInfo.LoginSystemInfos = infoSystems.Values.Select(x => x.ToLoginSystemInfo()).ToList(); /*权限部分*/ IEnumerable <Authority> authorities = this._repMediator.AuthorityRep.FindByRoles(roleIds, null); loginInfo.LoginAuthorityInfos = authorities.Select(x => x.ToLoginAuthorityInfo()).ToList(); /*菜单部分*/ IEnumerable <Guid> authorityIds = authorities.Select(x => x.Id); IEnumerable <Menu> menus = this._repMediator.MenuRep.FindByAuthorities(authorityIds, null); menus = menus.TailRecurseParentNodes(); loginInfo.LoginMenuInfos = menus.ToLoginMenuInfoTree(null); #endregion //以公钥为键,登录信息为值,存入分布式缓存 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(GlobalSetting.AuthenticationTimeout)); //获取客户端IP string ip = this.GetClientIp(); //生成登录记录 LoginRecord loginRecord = new LoginRecord(publicKey, user.Number, user.Name, ip, clientId); this._unitOfWork.RegisterAdd(loginRecord); this._unitOfWork.Commit(); return(loginInfo); }
/// <summary> /// 方法结束事件 /// </summary> /// <param name="context">方法元数据</param> private void OnExit(MethodAdviceContext context) { if (context.ReturnValue == null) { return; } string cacheKey = this.BuildCacheKey(context); if (this._expiredSpan.HasValue) { CacheMediator.Set(cacheKey, context.ReturnValue, DateTime.Now.Add(this._expiredSpan.Value)); } else { CacheMediator.Set(cacheKey, context.ReturnValue); } }
/// <summary> /// 获取登录信息 /// </summary> /// <returns>登录信息</returns> public LoginInfo GetLoginInfo() { if (OperationContext.Current != null) { //获取消息头 MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders; if (!headers.Any(x => x.Name == CommonConstants.WCFAuthenticationHeader && x.Namespace == GlobalSetting.ApplicationId)) { return(null); } Guid publicKey = headers.GetHeader <Guid>(CommonConstants.WCFAuthenticationHeader, GlobalSetting.ApplicationId); LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); return(loginInfo); } return(null); }
/// <summary> /// 执行中间件 /// </summary> public async Task Invoke(HttpContext context) { if (AspNetSetting.Authorized) { //读Header string publicKey = context.Request.Headers[SessionKey.PublicKey]; if (string.IsNullOrWhiteSpace(publicKey)) { //读QueryString publicKey = context.Request.Query[SessionKey.PublicKey]; } if (string.IsNullOrWhiteSpace(publicKey)) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; context.Response.Headers.Append("ErrorMessage", "Public key not found"); await this._next.Invoke(context); } else { LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey); if (loginInfo == null) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; context.Response.Headers.Append("ErrorMessage", "Login info expired"); await this._next.Invoke(context); } else { IIdentity identity = new GenericIdentity(loginInfo.LoginId); context.User = new GenericPrincipal(identity, null); await this._next.Invoke(context); } } } else { await this._next.Invoke(context); } }
/// <summary> /// 执行授权过滤器事件 /// </summary> public async Task <HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext context, CancellationToken cancellationToken, Func <Task <HttpResponseMessage> > continuation) { if (AspNetSetting.Authorized && !this.HasAttr <AllowAnonymousAttribute>(context.ActionDescriptor)) { if (!context.Request.Headers.TryGetValues(SessionKey.PublicKey, out IEnumerable <string> headers)) { HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized) { Content = new StringContent("身份认证消息头不存在,请检查程序!") }; return(httpResponseMessage); } //读取消息头中的公钥 Guid publicKey = new Guid(headers.Single()); //认证 lock (_Sync) { //以公钥为键,查询分布式缓存,如果有值则通过,无值则不通过 LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); if (loginInfo == null) { HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.Unauthorized) { Content = new StringContent("身份过期,请重新登录!") }; return(httpResponseMessage); } //通过后,重新设置缓存过期时间 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(GlobalSetting.AuthenticationTimeout)); return(continuation().Result); } } return(await continuation()); }
/// <summary> /// 接收请求后事件 /// </summary> /// <param name="request">请求消息</param> /// <param name="channel">信道</param> /// <param name="instanceContext">WCF实例上下文</param> /// <returns></returns> public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { //如果是身份认证接口,无需认证 if (OperationContext.Current.EndpointDispatcher.ContractName != "IAuthenticationContract") { //获取消息头 MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders; #region # 验证消息头 if (!headers.Any(x => x.Name == CommonConstants.WcfAuthHeaderName && x.Namespace == CommonConstants.WcfAuthHeaderNamespace)) { throw new NullReferenceException("身份认证消息头不存在,请检查程序!"); } #endregion //读取消息头中的公钥 Guid publicKey = headers.GetHeader <Guid>(CommonConstants.WcfAuthHeaderName, CommonConstants.WcfAuthHeaderNamespace); //认证 lock (_Sync) { //以公钥为键,查询分布式缓存,如果有值则通过,无值则不通过 LoginInfo loginInfo = CacheMediator.Get <LoginInfo>(publicKey.ToString()); if (loginInfo == null) { throw new NoPermissionException("身份过期,请重新登录!"); } //通过后,重新设置缓存过期时间 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(_Timeout)); } } return(null); }
//Private #region # 方法进入事件 —— bool OnEntry(MethodAdviceContext context) /// <summary> /// 方法进入事件 /// </summary> /// <param name="context">方法元数据</param> private bool OnEntry(MethodAdviceContext context) { bool hasCache = false; string cacheKey = this.BuildCacheKey(context); object returnValue = CacheMediator.Get <object>(cacheKey); if (returnValue != null) { if (this._expiredSpan.HasValue) { CacheMediator.Set(cacheKey, returnValue, DateTime.Now.Add(this._expiredSpan.Value)); } else { CacheMediator.Set(cacheKey, returnValue); } context.ReturnValue = returnValue; hasCache = true; } return(hasCache); }
//Implements #region # 登录 —— LoginInfo Login(string loginId, string password) /// <summary> /// 登录 /// </summary> /// <param name="loginId">登录名</param> /// <param name="password">密码</param> /// <returns>登录信息</returns> public LoginInfo Login(string loginId, string password) { #region # 验证参数 if (string.IsNullOrWhiteSpace(loginId)) { throw new ArgumentNullException(nameof(loginId), "用户名不可为空!"); } if (string.IsNullOrWhiteSpace(password)) { throw new ArgumentNullException(nameof(password), "密码不可为空!"); } #endregion lock (_Sync) { /****************验证机器****************/ this.AuthenticateMachine(); /****************登录验证****************/ User currentUser = this._repMediator.UserRep.SingleOrDefault(loginId); #region # 验证 if (currentUser == null) { throw new InvalidOperationException($"用户名\"{loginId}\"不存在!"); } if (!currentUser.Enabled) { throw new InvalidOperationException("用户已停用!"); } if (currentUser.Password != password.ToMD5()) { throw new InvalidOperationException("登录失败,密码错误!"); } #endregion //生成公钥 Guid publicKey = Guid.NewGuid(); //生成登录信息 LoginInfo loginInfo = new LoginInfo(currentUser.Number, currentUser.Name, publicKey); #region # 登录信息的信息系统部分/菜单部分/权限部分 ICollection <Guid> roleIds = this._repMediator.RoleRep.FindIds(loginId, null); /*信息系统部分*/ IEnumerable <string> systemNos = currentUser.GetInfoSystemNos(); IDictionary <string, InfoSystem> systems = this._repMediator.InfoSystemRep.Find(systemNos); loginInfo.LoginSystemInfos.AddRange(systems.Values.Select(x => x.ToLoginSystemInfo())); /*菜单部分*/ IEnumerable <Guid> authorityIds = this._repMediator.AuthorityRep.FindIdsByRole(roleIds); IEnumerable <Menu> menus = this._repMediator.MenuRep.FindByAuthority(authorityIds, null); menus = menus.TailRecurseParentNodes(); ICollection <LoginMenuInfo> menuTree = menus.ToTree(null); loginInfo.LoginMenuInfos.AddRange(menuTree); /*权限部分*/ IEnumerable <Authority> authorities = this._repMediator.AuthorityRep.FindByRole(roleIds); loginInfo.LoginAuthorityInfos = authorities.GroupBy(x => x.SystemNo).ToDictionary(x => x.Key, x => x.Select(y => y.ToLoginAuthorityInfo()).ToArray()); #endregion //以公钥为键,登录信息为值,存入分布式缓存 CacheMediator.Set(publicKey.ToString(), loginInfo, DateTime.Now.AddMinutes(_Timeout)); //获取客户端IP MessageProperties properties = OperationContext.Current.IncomingMessageProperties; string ip = "localhost"; if (properties.ContainsKey(RemoteEndpointMessageProperty.Name)) { RemoteEndpointMessageProperty endpoint = (RemoteEndpointMessageProperty)properties[RemoteEndpointMessageProperty.Name]; ip = endpoint.Address; } //生成登录记录 this.GenerateLoginRecord(publicKey, ip, currentUser.Number, currentUser.Name); return(loginInfo); } }