• WCF中的用户验证


    在system.serviceModel的client中添加endpoint节点,设置名称、地址、bingding类型、contract契约,并使用behaviorConfiguration传递用户信息。

    <endpoint name="名称" address="http://test.svc" binding="basicHttpBinding" contract="契约" behaviorConfiguration="IdentityTransfer"/>

    IdentityTransfer在behaviors的endpointBehaviors中添加。

    <behavior name="IdentityTransfer">
            <IdentityClientTransfer/>
    </behavior>

    IdentityClientTransfer是自定义的扩展处理,在extensions中说明:

    <behaviorExtensions>
            <add name="IdentityClientTransfer" type="命名空间.IdentityClientTransferBehavior, 程序集"/>
    </behaviorExtensions>

    以下直接帖相关的Class:

    public class IdentityClientTransferBehavior : BehaviorExtensionElement, IEndpointBehavior
        {
    
            [ConfigurationProperty("authenticationType")]
            public string AuthenticationType
            {
                get { return (string)base["authenticationType"]; }
                set { base["authenticationType"] = value; }
            }
    
            [ConfigurationProperty("user")]
            public string User
            {
                get { return (string)base["user"]; }
                set { base["user"] = value; }
            }
    
            [ConfigurationProperty("password")]
            public string Password
            {
                get { return (string)base["password"]; }
                set { base["password"] = value; }
            }
    
            [ConfigurationProperty("domain")]
            public string Domain
            {
                get { return (string)base["password"]; }
                set { base["password"] = value; }
            }
    
            [ConfigurationProperty("cacheouttime", DefaultValue = 110D, IsRequired = false)]
            public double CacheOutTime
            {
                get { return (double)base["cacheouttime"]; }
                set { base["cacheouttime"] = value; }
            }
    
            public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
                //nothing to do
            }
    
            public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
            {
                if (string.IsNullOrEmpty(AuthenticationType))
                    clientRuntime.MessageInspectors.Add(new IdentityClientMessageInspector());
                else
                    clientRuntime.MessageInspectors.Add(new IdentityClientMessageInspector(()=>GetUserIdentity()));
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
            {
                //nothing to do
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
                //nothing to do
            }
    
            protected override object CreateBehavior()
            {
                return CreateInstance();
            }
    
            public override Type BehaviorType
            {
                get { return typeof(IdentityClientTransferBehavior); }
            }
    
            IdentityClientTransferBehavior CreateInstance()
            {
                return new IdentityClientTransferBehavior()
                {
                    AuthenticationType = this.AuthenticationType,
                    Domain = this.Domain,
                    User = this.User,
                    Password = this.Password,
                    CacheOutTime = this.CacheOutTime
                };
            }
    
            UserIdentity GetUserIdentity()
            {
                Security.Dtos.UserIdentityDto userIdnetityDto = null;
    
                switch (AuthenticationType.Trim().ToUpper())
                {
                    case AuthenticationTypes.ANONYMOUS://密码登陆
                        userIdnetityDto = new Security.SecurityClient().AnonymousLogin(Password);
                        break;
                    case AuthenticationTypes.USER_PASSWORD://用户密码登陆
                        userIdnetityDto = new Security.SecurityClient().LoginByUserAccount(User, Password);
                        break;
                    case AuthenticationTypes.ACTIVE_DIRECTORY://域账户登陆
                        userIdnetityDto = new Security.SecurityClient().LoginByDomainAccount(User, Password, Domain);
                        break;
                    case AuthenticationTypes.WINDOWS_IDENTITY://系统集成登陆
                        userIdnetityDto = new Security.SecurityClient().LoginByWindowsIdentity(System.Security.Principal.WindowsIdentity.GetCurrent());
                        break;
                }
    
                var userIdentity = new Security.UserIdentity(userIdnetityDto);
    
                return userIdentity;
            }
    
        }
    [Serializable]
        public class SecurityClient
        {
            public UserIdentityDto AnonymousLogin(string password)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>().AnonymousLogin(password);
            }
    
            public UserIdentityDto LoginByUserAccount(string userName, string password)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>().LoginByUserAccount(userName,password);
            }
    
            public UserIdentityDto LoginByDomainAccount(string domainAccountName, string password, string domainName)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>().LoginByDomainAccount(domainAccountName, password, domainName);
            }
    
            public UserIdentityDto LoginByWindowsIdentity(WindowsIdentity windowsIdentity)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>(typeof(ISecurityProviderService).FullName + ".WindowsIntegration").LoginByWindowsIdentity();
            }
    
            public UserPrincipalDto GetUserPrincipalByToken(string userToken)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>().GetUserPrincipalByToken(userToken);
            }
    
            public void Logout(string userToken)
            {
                ClientFactory.CreateClient<ISecurityProviderService>().Logout(userToken);
            }
    
            public bool CheckUserToken(string userToken)
            {
                return ClientFactory.CreateClient<ISecurityProviderService>().CheckUserToken(userToken);    
            }
        }
    public class IdentityClientMessageInspector : IClientMessageInspector
        {
            private Func<UserIdentity> _getUserIdentity { get; set; }
    
            private const string USER_IDENTITY_TOKEN = "User_Identity_Token";
    
            public IdentityClientMessageInspector()
            { }
    
            public IdentityClientMessageInspector(Func<UserIdentity> getUserIndentity)
            {
                _getUserIdentity = getUserIndentity;
            }
    
            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
    
            }
    
            public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
            {
                //If there is a user identity that be passed in, assign the current context identity as ClientUser, and then transfer it to server side;
                //Otherwise transfer the current context identity to server side. 
    
                UserIdentity userIdentity = null;
    
                if (_getUserIdentity != null)
                {
                    //Get user identity for each request to prevent from the token expiration exception  
                    userIdentity = _getUserIdentity.Invoke();
    
                    if (UserIdentity.Current != null)
                        userIdentity.ClientUser = UserIdentity.Current.ClientUser.Clone();
                }
                else
                {
                    userIdentity = UserIdentity.Current;
                }
    
                //Add user identity token into message headers
                if (userIdentity != null)
                {
                    request.Headers.Add(MessageHeader.CreateHeader(
                                USER_IDENTITY_TOKEN,
                                string.Empty,
                                userIdentity.Serialize()));
                }
    
                return null;
            }
        }
    [Serializable]
        public class UserIdentity : IIdentity, IDisposable
        {
            /// <summary>
            /// Current User Id
            /// </summary>
            public int UserId { get; set; }
    
            /// <summary>
            /// Current user account
            /// </summary>
            public string Account { get; set; }
    
            /// <summary>
            /// Current user name
            /// </summary>
            public string Name { get; set; }
    
            /// <summary>
            /// Current user AuthenticationType. Current custom AuthenticationType:<see cref="AuthenticationTypes"/>
            /// </summary>
            public string AuthenticationType { get; set; }
    
            /// <summary>
            /// Is current user authenicatd
            /// </summary>
            public bool IsAuthenticated { get; set; }
    
            /// <summary>
            /// Current login user's usertoken. When user hasn't login the system, the usertoken is empty.
            /// </summary>
            public string UserToken { get; set; }
    
            public bool NeedToChangePassword { get; set; }
    
            public string ClientIP { get; set; }
    
            public UserIdentity ClientUser { get; set; }
    
            /// <summary>
            /// Instance UserIdentity by user identity data transfer object.
            /// </summary>
            /// <param name="dto">User identity data transfer object</param>
            public UserIdentity(UserIdentityDto dto)
            {
                InitialUserIndentity(dto);
            }
    
            public UserIdentity() { }
    
            #region Login
    
            /// <summary>
            /// Instance UserIdentity by user account. User will call login service and login system by user account while instance UserIdenity in this mode.
            /// </summary>
            /// <param name="userName">User account name</param>
            /// <param name="password">Account password</param>
            public UserIdentity(string userName, string password)
            {
                var client = new SecurityClient();
                UserIdentityDto dto = client.LoginByUserAccount(userName, password);
                InitialUserIndentity(dto);
            }
    
            /// <summary>
            /// Instance UserIdentity by current windows identity. User will call login service and login system by current windows identity 
            /// while instance UserIdenity in this mode.
            /// </summary>
            /// <param name="windowsIdentity">WindowsIdentity<see cref="WindowsIdentity"/></param>
            public UserIdentity(WindowsIdentity windowsIdentity)
            {
                var client = new SecurityClient();
                UserIdentityDto dto = client.LoginByWindowsIdentity(windowsIdentity);
                InitialUserIndentity(dto);
            }
    
            /// <summary>
            /// Instance UserIdentity by domain account. User will call login service and login system by domain account
            /// while instance UserIdenity in this mode.
            /// </summary>
            /// <param name="domainAccountName">Domain account name</param>
            /// <param name="password">Domain account password</param>
            /// <param name="domainName">Domain name</param>
            public UserIdentity(string domainAccountName, string password, string domainName)
            {
                var client = new SecurityClient();
                UserIdentityDto dto = client.LoginByDomainAccount(domainAccountName, password, domainName);
    
                InitialUserIndentity(dto);
            }
    
            public UserIdentity(string password)
            {
                var client = new SecurityClient();
                UserIdentityDto dto = client.AnonymousLogin(password);
                InitialUserIndentity(dto);
            }
    
            public bool CheckUserToken()
            {
                var client = new SecurityClient();
                return client.CheckUserToken(this.UserToken);
            }
    
            public string Serialize()
            {
                return De.Framework.Utility.Serialization.XmlObjSerializer.Serialize(this);
            }
    
            public static UserIdentity Deserialize(string userIdentityContent)
            {
                return De.Framework.Utility.Serialization.XmlObjSerializer.Deserialize<UserIdentity>(userIdentityContent);
            }
    
            /// <summary>
            /// Get current user identity from the current user principal.
            /// If there is not the information, return null;
            /// </summary>
            public static UserIdentity Current
            {
                get
                {
                    if (UserPrincipal.Current == null)
                        return null;
    
                    return UserPrincipal.Current.Identity as UserIdentity;
                }
            }
    
            /// <summary>
            /// Initial current user identity
            /// </summary>
            /// <param name="dto">User identity data transfer object</param>
            private void InitialUserIndentity(UserIdentityDto dto)
            {
                this.UserId = dto.UserId;
                this.IsAuthenticated = dto.IsAuthenticated;
                this.Account = dto.UserAccount;
                this.Name = dto.UserName;
                this.UserToken = dto.UserToken;
                this.AuthenticationType = dto.AuthenticationType;
                this.NeedToChangePassword = dto.NeedToChangePassword;
    
                System.Net.IPAddress[] address = System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName());
                if (address != null)
                {
                    foreach (var item in address)
                    {
                        if (item.AddressFamily.Equals(AddressFamily.InterNetwork))
                        {
                            this.ClientIP = item.ToString();
                            break;
                        }
                    }
                }
    
                if (this.ClientUser == null)
                    this.ClientUser = this.Clone();
            }
    
            /// <summary>
            /// Dispose current user identity and logout the system.
            /// </summary>
            public void Dispose()
            {
                //var client = new SecurityClient();
                //client.Logout(UserToken);
            }
    
            public UserIdentity Clone()
            {
                return this.MemberwiseClone() as UserIdentity;
            }
    
            #endregion
    
            public static string GetClientIP()
            {
                var userIdentity = UserIdentity.Current;
    
                if (userIdentity != null && userIdentity.ClientUser != null)
                {
                    return userIdentity.ClientUser.ClientIP;
                }
    
                return string.Empty;
            }
        }
    /// <summary>
        /// User principal, inherit from IPrincipal.<see cref="IPrincipal"/>
        /// UserPrincpal contains user identity and user roles, used for authentication and authrization.
        /// </summary>
        [Serializable]
        public class UserPrincipal : IPrincipal, IDisposable
        {
            private const string USER_PRINCIPAL = "__USER_PRINCIPAL";
    
            /// <summary>
            /// <see cref="UserIdentity"/>
            /// </summary>
            private UserIdentity _identity;
    
            /// <summary>
            /// <see cref="Identity"/>
            /// </summary>
            public IIdentity Identity
            {
                get { return _identity; }
            }
    
            private List<Role> _roles;
            public List<Role> Roles
            {
                get { return _roles; }
                set { _roles = value; }
            }
    
            private List<Permission> _permissions;
            public List<Permission> Permissions
            {
                get { return _permissions; }
                set { _permissions = value; }
            }
    
            /// <summary>
            /// Current login user principal. If haven't login the system, the UserPrincipal.Current is null.
            /// </summary>
            public static UserPrincipal Current
            {
                get
                {
                    UserPrincipal userPrincipal = null;
    
                    if (OperationUserPrincipalContext.Current != null)
                    {
                        userPrincipal = OperationUserPrincipalContext.Current.UserPrincipal;
                    }
                    else
                    {
                        userPrincipal = CallContext.LogicalGetData(USER_PRINCIPAL) as UserPrincipal;
    
                        if (userPrincipal == null)
                            userPrincipal = AppDomain.CurrentDomain.GetData(USER_PRINCIPAL) as UserPrincipal;
                    }
    
                    return userPrincipal;
                }
                set
                {
                    if (OperationUserPrincipalContext.Current != null)
                    {
                        OperationUserPrincipalContext.Current.UserPrincipal = value;
                    }
                    else
                    {
                        CallContext.LogicalSetData(USER_PRINCIPAL, value);
    
                        AppDomain.CurrentDomain.SetData(USER_PRINCIPAL, value);
                    }
                }
            }
    
            /// <summary>
            /// Instance UserPrincipal by UserIdentity.<see cref="UserIdentity"/>
            /// </summary>
            /// <param name="userIdentity">User identity</param>
            /// <param name="isLoggingin">Yes:user logging in the system. No:calling service</param>
            public UserPrincipal(UserIdentity userIdentity)
            {
                if (userIdentity == null)
                    throw new ArgumentNullException("userIdentity");
    
                var client = new SecurityClient();
                InitialUserPrincipal(client.GetUserPrincipalByToken(userIdentity.UserToken));
            }
    
            /// <summary>
            /// Instance UserPrincipal by user principal data transfer object after calling the service.
            /// </summary>
            /// <param name="dto">User principal data transfer object</param>
            public UserPrincipal(UserPrincipalDto dto)
            {
                InitialUserPrincipal(dto);
            }
    
            public UserPrincipal(string userToken)
            {
                var client = new SecurityClient();
                UserPrincipalDto dto = client.GetUserPrincipalByToken(userToken);
                if (dto != null)
                {
                    _identity = new UserIdentity(dto.UserIdentityDto);
    
                    InitialUserPrincipal(dto);
                }
            }
    
            /// <summary>
            /// Initial UserPrincipal by user principal data transfer object.
            /// </summary>
            /// <param name="dto">User principal data transfer object</param>
            private void InitialUserPrincipal(UserPrincipalDto dto)
            {
                _identity = new UserIdentity(dto.UserIdentityDto);
    
                if (_permissions == null)
                    _permissions = new List<Permission>();
    
                foreach (SecurityRoleDto securityRoleDto in dto.RoleDtoList)
                {
                    var permissions = securityRoleDto.GetPermissions();
                    permissions.ForEach(o => _permissions.Add(new Permission(o)));
                }
    
                if (_roles == null)
                    _roles = new List<Role>();
    
                dto.RoleDtoList.ForEach(a => _roles.Add(new Role(a)));
            }
    
            /// <summary>
            /// Is current user the specified role type
            /// </summary>
            /// <param name="role">Specified role code</param>
            /// <returns>True, is the specified role type. else, not</returns>
            public bool IsInRole(string role)
            {
                return Roles.Any(o => o.Code.ToLower() == role.ToLower());
            }
    
            /// <summary>
            /// Does current user have right to the specified system resource with the specified operation
            /// </summary>
            /// <param name="systemResourceCode">The specified system resource</param>
            /// <param name="systemAccessCode">The specified operation</param>
            /// <returns>True, has right. else, not</returns>
            public bool HasRight(string systemResourceCode, string systemAccessCode)
            {
                return
                    Permissions.Any(
                        o => o.SystemResourceCode.ToLower() == systemResourceCode.ToLower() && o.SystemAccessCode.ToLower() == systemAccessCode.ToLower());
            }
    
            public void Dispose()
            {
                new SecurityClient().Logout(_identity.UserToken);
            }
        }
    public class OperationUserPrincipalContext
        {
            static System.Collections.Concurrent.ConcurrentDictionary<int, OperationUserPrincipalContext> _contexts = new System.Collections.Concurrent.ConcurrentDictionary<int, OperationUserPrincipalContext>();
    
            public UserPrincipal UserPrincipal { get; set; }
    
            public int OperationContextHashCode { get; private set; }
    
            private OperationUserPrincipalContext(int operationContextHashCode)
            {
                OperationContextHashCode = operationContextHashCode;
            }
    
            public static OperationUserPrincipalContext Current
            {
                get
                {
                    if (OperationContext.Current == null)
                        return null;
    
                    var operationContextHashCode = OperationContext.Current.GetHashCode();
    
                    var currentContext = _contexts.GetOrAdd(operationContextHashCode, (id) =>
                        {
                            //Listen operation completed event
                            OperationContext.Current.OperationCompleted += (s, e) =>
                                {
                                    //Release OperationUserPrincipalContext
                                    OperationUserPrincipalContext context;
                                    _contexts.TryRemove(id, out context);
                                };
    
                            return new OperationUserPrincipalContext(operationContextHashCode);
                        });
    
                    return currentContext;
                }
            }
        }

    WCF服务端直接使用UserIdentity.Current即可获取当前访问用户。

  • 相关阅读:
    Oracle- 表的自增长创建
    C#- 写Windows服务
    基于redis分布式缓存实现(新浪微博案例)
    分布式集群系统下的高可用session解决方案
    Hibernate 缓存介绍
    MongoDB 安装(Window/Linux)
    MongoDB 优点
    MongoDB 介绍
    浅析数据一致性
    mysql常用函数汇总
  • 原文地址:https://www.cnblogs.com/tingqianzhu/p/8509364.html
Copyright © 2020-2023  润新知