ビットマップアルゴリズムのユーザー検証への応用


先日、ブログ園で2つの整数集合の比較アルゴリズムの問題を議論する投稿を見ました.ほほほ、実はいかなる整数集合の問題もビットマップアルゴリズムで解決することができます.簡単に言えば,値を配列下標に変換し,O(n)複雑度をO(1)複雑度に低減して最高効率を得る.もちろん、少しの空間を犠牲にします.
単純な整数集合比較問題を解決するのは,純粋な理論にすぎない.実際には、ビットマップアルゴリズムは、ユーザがログインした後のインタフェース検証に適用することができる.サービス側の設計も複雑なところはなく、配列を維持することです.ただし,この配列は単純な整数集合ではなく,オブジェクトリストである.この設計の最大の利点は、findメソッドではなく、下付きオブジェクトに直接アクセスし、データベースをクエリーする必要がなく、時間消費を最小限に抑えることです.
では、コードを見てみましょう.まずSessionクラスです.このクラスには必要なユーザー情報が含まれています.その中で最も重要な属性はIDであり、このIDの値はリスト内のオブジェクトの下付き値である.
    public class Session
    {

        /// 
        ///   ID
        /// 
        public int ID { get; set; }

        /// 
        ///   ID
        /// 
        public Guid SessionId { get; set; }

        /// 
        ///     ID
        /// 
        public Guid UserId { get; set; }

        /// 
        ///     ID
        /// 
        public Guid? DeptId { get; set; }

        /// 
        ///     
        /// 
        public string LoginName { get; set; }

        /// 
        ///      
        /// 
        public string UserName { get; set; }

        /// 
        ///       
        /// 
        public string DeptName { get; set; }

        /// 
        /// WCF     
        /// 
        public string BaseAddress { get; set; }

        /// 
        ///     
        /// 
        public string Signature { get; set; }

        /// 
        ///     
        /// 
        public bool Validity { get; set; }

        /// 
        ///      
        /// 
        public string MachineId { get; set; }

        /// 
        ///       
        /// 
        public DateTime LastConnect { get; set; }

        /// 
        ///       
        /// 
        public LoginResult LoginStatus { get; set; }

    }

次にOnlineManagementクラスです.このクラスは、サービスが開始されたときにインスタンス化され、セッションの正当性を検証する静的メソッドを提供します.ここで,キーポイントはvar us=Sessions[obj.ID]という文であり,下付きアクセスにより時間の複雑さをO(1)に低減した.
    public class OnlineManage
    {

        /// 
        ///       
        /// 
        public static List Sessions { get; set; }

        /// 
        ///        
        /// 
        public static int MaxAuthorized { get; set; }

        /// 
        ///     
        /// 
        public OnlineManage()
        {
            Sessions = new List();
            MaxAuthorized = Convert.ToInt32(ConfigurationManager.AppSettings["MaxAuthorized"]);
        }

        /// 
        ///        
        /// 
        /// 
        /// 
        public static bool Verification(Session obj)
        {
            if (obj == null || obj.ID >= Sessions.Count) return false;

            var us = Sessions[obj.ID];
            if (us.SessionId != obj.SessionId || us.Signature != obj.Signature || !us.Validity) return false;

            us.LastConnect = DateTime.Now;
            return true;
        }

    }

最後にログイン検証方法であり,この方法は,入力されたSessionオブジェクトが既に存在するか(以前システムにログインしていた)か否かをO(n)の方法で判断し,存在しない場合はデータベースを問合せて新しいSessionオブジェクトを構築してリストに入れる.最後に、システムにログインしたかどうかにかかわらず、このメソッドはクライアントのセッションオブジェクトエンティティに戻ります.クライアントはサービス側インタフェースを呼び出すたびに,Sessionをパラメータとして正当性検証を行うことができる.
        /// 
        ///         
        /// 
        /// Session    
        /// Session    
        public Session UserLogin(Session obj)
        {
            if (obj == null) return null;

            if (OnlineManage.Sessions.Count >= OnlineManage.MaxAuthorized)
            {
                obj.LoginStatus = LoginResult.Unauthorized;
                return obj;
            }

            var pw = obj.Signature;
            var us = OnlineManage.Sessions.Find(s => s.LoginName == obj.LoginName);
            if (us == null)
            {
                var user = CommonDAL.GetUser(obj.LoginName);
                if (user == null)
                {
                    obj.LoginStatus = LoginResult.NotExist;
                    return obj;
                }

                obj.ID = OnlineManage.Sessions.Count;
                obj.UserId = user.ID;
                obj.UserName = user.Name;
                obj.Signature = user.Password;
                obj.Validity = user.Validity;

                OnlineManage.Sessions.Add(obj);
                us = OnlineManage.Sessions[obj.ID];
            }
            else if (us.SessionId != Guid.Empty)
            {
                us.LoginStatus = us.MachineId != obj.MachineId ? LoginResult.Online : LoginResult.Multiple;
            }
            else
            {
                us.SessionId = obj.SessionId;
                us.LoginStatus = LoginResult.Success;
            }

            //      
            if (!us.Validity) us.LoginStatus = LoginResult.Banned;

            //      
            if (us.Signature != pw) us.LoginStatus = LoginResult.Failure;

            us.LastConnect = DateTime.Now;
            return us;
        }

入力パラメータによって検証される例としては、終了後にログイン状態を削除する(SessionIdを空のGUID値にする)などがある.そうだ、もう一つのメリットは、1つのアカウントが閉鎖されさえすれば、ユーザーが終了するのを待つのではなく、すぐに有効になることです.
        /// 
        ///         
        /// 
        /// Session    
        ///    Session ID
        /// bool       
        public bool DelOnlineUser(Session us, int? sid)
        {
            if (us == null) return false;

            if (!OnlineManage.Verification(us)) return false;

            OnlineManage.Sessions[sid ?? us.ID].SessionId = Guid.Empty;
            return true;
        }

        /// 
        ///   ID  /    
        /// 
        ///     
        ///   ID
        /// true:  ;false:  
        /// bool       
        public bool UpdateUserStatus(Session us, Guid id, bool validity)
        {
            if (!OnlineManage.Verification(us)) return false;

            var sql = string.Format("update SYS_User set Validity = '{0}' where ID = '{1}'", validity, id);
            if (SqlHelper.SqlNonQuery(sql) > 0)
            {
                OnlineManage.Sessions.Find(s => s.UserId == id).Validity = validity;
                return true;
            }
            return false;
        }

ここには基本的にこれらを書いて、もっと多くのコードを私のcodeに移動してください.うんうん、整理するのに少し時間がかかります.