Example #1
0
        /// <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));
        }
Example #2
0
        /// <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));
        }
Example #12
0
        //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);
            }
        }
Example #17
0
        /// <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);
        }
Example #20
0
        //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);
            }
        }