上節內容:
1:通用社區登陸組件技術分享(開源)上篇:OAuth 授權登陸介紹
2:通用社區登陸組件技術分享(開源)中篇:OAuth 登陸組件流程及組件集成方法
本節內容:
1:簡述組件設計的過程及思路及部分重點源碼講解
2:源碼下載
3:擴展機制說明
附源碼截圖:等會看以下思路時,可以對照着看:
一:簡述組件設計的過程及思路
1:為什么想到弄成組件?
2:本人設計組件的原則?
2.1:讓用戶以最簡單的方式使用或調用組件,編寫代碼量最小化;
2.2:所有的設計,都參考第2.1點。
3:本人組件設計的簡單思路過程:(5行代碼的設計思路)
3.1:用戶的操作UI設計:

如上圖的第三方授權登陸如何展示?
在html里直接寫死?感覺不給力,而且如果擴展多幾個第三方登陸時,又要去組合網址,是件麻煩事。
所以我想到了應該有UI類,應該有個GetHtml(),這樣來解決讓調用更簡單。
實現UI.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里可以獲取所有授權類型進行遍歷組裝。
代碼:
/// <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 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(
)
三:擴展機制說明
看完本文,下完源碼,也許您可能會有以下功能需要進行調整,這里給出指導與說明:
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