通用社區登陸組件技術分享(開源)下篇:OAuth 源碼下載及原理解說


上節內容:

1:通用社區登陸組件技術分享(開源)上篇:OAuth 授權登陸介紹

2:通用社區登陸組件技術分享(開源)中篇:OAuth 登陸組件流程及組件集成方法

 

本節內容:

1:簡述組件設計的過程及思路及部分重點源碼講解

2:源碼下載

3:擴展機制說明 

附源碼截圖:等會看以下思路時,可以對照着看:

 

一:簡述組件設計的過程及思路

 

1:為什么想到弄成組件?

當重復的代碼或相似的事件>=2個時,我都會想一下,是否還可能有第3個,第4個相近的,如果有,就會統一處理,組件就是設計的再通用一些。

 

2:本人設計組件的原則? 

2.1:讓用戶以最簡單的方式使用或調用組件,編寫代碼量最小化;

2.2:所有的設計,都參考第2.1點。

 

3:本人組件設計的簡單思路過程:(5行代碼的設計思路)

3.1:用戶的操作UI設計:

 

 

如上圖的第三方授權登陸如何展示?

在html里直接寫死?感覺不給力,而且如果擴展多幾個第三方登陸時,又要去組合網址,是件麻煩事。

所以我想到了應該有UI類,應該有個GetHtml(),這樣來解決讓調用更簡單。

 

實現UI.GetHtml()方法:
這里也是有點知識點的,為了讓代碼簡潔化,我花了不少時間思考,通過良好的代碼組合設計,減少代碼量的編寫。

 

於是,我用了一個常用方法,來優化這種設計:

         public  static  string GetHtml()
        {
             string link =  " <a href=\"{0}\" target=\"_blank\"><img src=\"{1}\" /></a> ";
            StringBuilder sb =  new StringBuilder();
             foreach (KeyValuePair< string,OAuth2Base> ob  in OAuth2Factory.ServerList)
            {
                 if (! string.IsNullOrEmpty(ob.Value.AppKey))
                {
                    sb.AppendFormat(link,  string.Format(ob.Value.OAuthUrl, ob.Value.AppKey,System.Web.HttpUtility.UrlEncode(ob.Value.CallbackUrl), ob.Key), ob.Value.ImgUrl);
                }
            }
             return sb.ToString();

         } 

這段代碼里,包含了幾種優化思路:

1:應該有一個方法,可以獲取當前所有的授權類型: OAuth2Factory.ServerList

2:授權類型應該包括一些配置項,可以直接讀取: ob.Value.OAuthUrl, ob.Value.AppKey,ob.Value.ImgUrl

 

在想出這種方法時,還沒開始設計OAuth2授權相關類,所以當時還只是偽代碼,隨着OAuth2類被完善,這里的代碼就簡單成型了。

 

OK,讓我們回頭看看:

3.2:OAuth授權類設計(傳說的抽象+工廠):

和數據庫多數據庫支持的設計思路如出一折。

 

1:應該有個基類:OAuth2Base(包括通用的方法和屬性)

2:繼續基類 OAuth2Base,實現不同的授權:SinaWeiboOAuth、QQAuth、其它...等!

3:有個工廠OAuth2Factory來返回當前的授權類型(正如數據庫組件來設計當前是操作哪種數據庫類型)

4:有個小工具類Tool,放幾個常用的小方法。

 

在OAuth2Factory里,我們通過預先注冊所有的子類授權,來匯總所有的授權類型。

所以GetHtml里可以獲取所有授權類型進行遍歷組裝。

代碼:

         static Dictionary< string, OAuth2Base> _ServerList;
         ///   <summary>
        
///  獲取所有的類型(新開發的OAuth2需要到這里注冊添加一下)
        
///   </summary>
         internal  static Dictionary< string, OAuth2Base> ServerList
        {
             get
            {
                 if (_ServerList ==  null)
                {
                    _ServerList =  new Dictionary< string, OAuth2Base>(StringComparer.OrdinalIgnoreCase);
                    _ServerList.Add(OAuthServer.SinaWeiBo.ToString(),  new SinaWeiBoOAuth()); // 新浪微博
                    _ServerList.Add(OAuthServer.QQ.ToString(),  new QQOAuth()); // QQ微博
                }
                 return _ServerList;
            }

} 


整體的設計並不復雜,只要實現后,就可以實現授權,並得到第三方的token和openid數據。

 

到這里,並未實現綁定賬號,於是我開始思考:

3.3 OAuth2 綁定網站的賬號實現第三方登陸:

如何和自己的網站的賬號實現綁定?

在原來網站的數據庫里,添加字段?或者創建新表,再進行設計?

考慮到這樣的設計,和網站代碼結合度必然很深,不可能做到通用型,而且不同網站,用的是不同的數據庫,那得編寫多少種不同的腳本?

所以思前想后,將數據外置存儲在外部文本,考慮到CYQ.Data V5已經接近完美的支持文本數據庫及CodeFirst操作,所以引用它做為默認的外置數據庫操作類。

 

當然拿到源碼后,如果對於外存儲過塊需要調整或使用其它框架,這個自行操作了,不干涉內政。 

 

內置的文本數據庫解決方案:

如果對比上面的源碼截圖,你應該發現,所以類都提到了,只剩下最后一個:OAuth2Account ,它就是實現和網站綁定的罪人。

代碼也很簡單的說(除了繼承自OrmBase和構造函數指定了表名和文本存儲路徑,基本上就是一個常見的實體類了):

public  class OAuth2Account:CYQ.Data.Orm.OrmBase
    {
         public OAuth2Account()
        {
             base.SetInit( this" OAuth2Account "" Txt Path={0}App_Data ");
        }
         private  int _ID;

         public  int ID
        {
             get
            {
                 return _ID;
            }
             set
            {
                _ID = value;
            }
        }
         private  string _OAuthServer;
         ///   <summary>
        
///  授權的服務類型
        
///   </summary>
         public  string OAuthServer
        {
             get
            {
                 return _OAuthServer;
            }
             set
            {
                _OAuthServer = value;
            }
        }
         private  string _Token;
         ///   <summary>
        
///  保存的Token
        
///   </summary>
         public  string Token
        {
             get
            {
                 return _Token;
            }
             set
            {
                _Token = value;
            }
        }
         private  string _OpenID;
         ///   <summary>
        
///  保存對應的ID
        
///   </summary>
         public  string OpenID
        {
             get
            {
                 return _OpenID;
            }
             set
            {
                _OpenID = value;
            }
        }
         private  string _BindAccount;
        
         private DateTime _ExpireTime;
         ///   <summary>
        
///  過期時間
        
///   </summary>
         public DateTime ExpireTime
        {
             get
            {
                 return _ExpireTime;
            }
             set
            {
                _ExpireTime = value;
            }
        }

         private  string _NickName;
         ///   <summary>
        
///  返回的第三方昵稱
        
///   </summary>
         public  string NickName
        {
             get
            {
                 return _NickName;
            }
             set
            {
                _NickName = value;
            }
        }
         private  string _HeadUrl;
         ///   <summary>
        
///  返回的第三方賬號對應的頭像地址。
        
///   </summary>
         public  string HeadUrl
        {
             get
            {
                 return _HeadUrl;
            }
             set
            {
                _HeadUrl = value;
            }
        }


         ///   <summary>
        
///  綁定的賬號
        
///   </summary>
         public  string BindAccount
        {
             get
            {
                 return _BindAccount;
            }
             set
            {
                _BindAccount = value;
            }
        }

在OAuth2Base基類里有兩個和內置文本數據庫打交首的函數:GetBindAccount和SetBindAccount:

         ///  添加綁定賬號
        
///   </summary>
        
///   <param name="bindAccount"></param>
        
///   <returns></returns>
         public  bool SetBindAccount( string bindAccount)
        {
             bool result =  false;
             if (! string.IsNullOrEmpty(openID) && ! string.IsNullOrEmpty(token) && ! string.IsNullOrEmpty(bindAccount))
            {
                 using (OAuth2Account oa =  new OAuth2Account())
                {
                     if (!oa.Exists( string.Format( " OAuthServer='{0}' and OpenID='{1}' ", server, openID)))
                    {
                        oa.OAuthServer = server.ToString();
                        oa.Token = token;
                        oa.OpenID = openID;
                        oa.ExpireTime = expiresTime;
                        oa.BindAccount = bindAccount;
                        oa.NickName = nickName;
                        oa.HeadUrl = headUrl;
                        result = oa.Insert(CYQ.Data.InsertOp.None);
                    }
                }
            }
             return result;
        }

由於是CodeFirst及設計的是文本數據庫,所以不用去兼容不同網站的數據庫,自動生成文本數據庫外置,只需要好好玩這個實體就可以了。

簡單的就介紹到這了,設計並不復雜,代碼量並不多,方法和成員也很少。

 

二:源碼下載

 

源碼點擊下載:  OAuth2_Source.rar(download times)

 

三:擴展機制說明 

 

看完本文,下完源碼,也許您可能會有以下功能需要進行調整,這里給出指導與說明:

1:界面UI的調整,具體看UI類,改動下即可。

2:增加授權種類:繼承OAuth2Base,參考已有的新浪微博和QQ進行操作,當然也可以聯系我讓我添加。

3:如何取得綁定后的表數據:只要調用new  OAuth2Account().Select().Bind(列表);

4:更換授權存儲介質,有兩種方式:

 

a:保留CYQ.Data V5版本,更換數據庫,只需要修改OAuth2Account類的構造函數的數據庫鏈接更換為您現在使用的數據庫鏈接即可。

CYQ.Data V5版本目前僅支持以下數據庫(mssql、mysql、oracle、aceess、sqlite、txt、xml),前三種需要授權使用,后四種免費使用。

b:移除CYQ.Data V5版本,更換底層組件,您只要重寫OAuth2Base中的 SetBindAccount和GetBindAccount兩個方法即可,然后自己另外存儲數據介質。

 

 

不管是哪種,對於有點開發經驗的新老手來說,都是相對比較簡單。


51cto大賽的參賽頁面,感謝路過的朋友也順手扔一票:http://blog.51cto.com/contest2012/2127378  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM