最近在做一個ASP.NET的系統,需要與Discuz整合實現雙向登入、註冊、修改密碼這些簡單的整合。
查了一些資料,最後還是選擇了官方提供的DiscuzToolkit,由於是開源的,所以用起來也方便,可以根據自己的需求做一些調整,在此也感謝DZ團隊。
第一步,當然還是將論壇安裝好,調試好,一切正常。
第二步,學習官方提供API文檔,http://nt.discuz.net/showtopic-66493.aspx。
第三步,查看官方提供的範例文件,http://nt.discuz.net/showtopic-81187.aspx。
第四步,項目中引入Discuz.Toolkit.dll(可直接將開源的項目添加到項目中)在網站中增加同步登入或註冊BBS帳號的方法,登入後或註冊完成時,如下:
View Code
//......登入代碼,登入成功後。//將登入資訊同步論壇,若沒有此會員則 註冊try{ DiscuzSession ds = DiscuzSessionHelper.GetSession(); Discuz.Toolkit.User user = null; try { user = ds.GetLoggedInUser().GetUserInfo(); } catch { } if (user == null || user.UserName != _user.UserName) { int uid = ds.GetUserID(_user.UserName); if (uid < 1) { //註冊新使用者 uid = ds.Register(_user.UserName, password, _user.Email, true); //填充基本資料 UserForEditing ufe = new UserForEditing(); ufe.RealName = _user.ActualName; ufe.IdCard = _user.IdCard; ufe.Mobile = _user.Phone; ufe.Phone = _user.Tel; ufe.Gender = _user.Gender.ToString(); ufe.NickName = _user.ActualName; ufe.GroupId = 10;//會員等級,可能採用特殊組來做一些其它應用。 ds.SetUserInfo(uid, ufe); } //同步登入 ds.Login(uid, password, true, 0, ""); }}catch (Exception ex){ LogHelper.WriteLog(ex); //錯誤記錄檔}
註冊或修改密碼對應的方法中,同步方法如下:
View Code
DiscuzSession ds = DiscuzSessionHelper.GetSession();int uid = 0;try{ //user = ds.GetLoggedInUser().GetUserInfo(); uid = ds.GetUserID(oldm.UserName); if (uid > 0) { //TODO:Discuz.Web.Services.Actions.Users 與 Discuz.Toolkit.User要對應起來 UserForEditing也一樣 //填充基本資料 UserForEditing ufe = new UserForEditing(); ufe.RealName = model.ActualName; ufe.IdCard = model.IdCard; ufe.Mobile = model.Phone; ufe.Phone = model.Tel; ufe.Gender = model.Gender.HasValue ? model.Gender.ToString() : "0"; ufe.NickName = model.ActualName; ufe.Password = model.Password; ufe.GroupId = model.Level.Value + 16; ufe.UserName = model.UserName; ufe.Email = model.Email; ufe.WebSite = ""; ufe.Location = ""; ds.SetUserInfo(uid, ufe); }}catch(Exception ex) { LogHelper.WriteLog(ex);}
以上GroupId、UserName屬性,在官方提供的開源項目UserForEditing類中沒有這兩個屬性,我們可以手動加入一下,同時要注意Discuz.Web.Services.Actions.Users 與 Discuz.Toolkit.User要對應起來 UserForEditing也一樣,如下:
View Code
//Discuz.Web.Services.API下UserForEditing類中增加:[JsonPropertyAttribute("group_id")]public int? GroupId; //使用者組ID[JsonPropertyAttribute("user_name")]public string UserName; //使用者名稱//Discuz.Web.Services.API.Actions下Users類的SetInfo()方法中增加://組別if (ufe.GroupId.HasValue){ userinfo.Groupid = ufe.GroupId.Value;}//使用者名稱if (ufe.UserName != null && ufe.UserName!=""){ userinfo.Username = ufe.UserName;}
如果Services中與前面調用的類屬性不一致的話,會出現序列化異常。
至此,我們已經實現了網站到論壇的同步登入、註冊、修改基本資料功能。
接下來就是實現,論壇到網站的同步登入、註冊、修改了,在這裡僅以登入狀態例,其它都差不多。
在這部分,我們就要使用官方提供的API操作了。
第一步,需要在後台“擴充” - “整合設定” 那裡加上調用URL,
上面,同步資料的URL地址為網站中的一個處理頁面,主要就是在這個頁面裡實現同步操作。
第二上,瞭解參數類型,DZ的同步機制是,在論壇有登入、註冊等動作操作後,通過javascript指令碼,向指定的URL地址傳遞參數的方式實現通訊,參數的基本格式為uid=1&user_name=test&time=1270283913981&action=login&sig=dskljoiwjelkjskdjfoiwelkjsifs。可以在官方提供的API說明中瞭解這些參數的作用,特別是sig的產生。
第三步,瞭解Discuz.Forum.Sync類中各種action的值及參數,方便在網站的api頁面中處理。
接下來,我們來實現登入同步,如下:
View Code
private DiscuzSession ds;private string action = "", user_name, password;private int uid = 0;protected void Page_Load(object sender, EventArgs e){ try { ds = DiscuzSessionHelper.GetSession(); if (!IsPostBack) { action = Handler.RequestQueryString("action"); uid = Handler.RequestQueryInt("uid"); user_name = Handler.RequestQueryString("user_name"); password = Handler.RequestQueryString("password"); if (action != "" && check_sig()) //驗證sig是否合法 { switch (action) { case "login": //同步登入:uid,user_name,time,action 正序後 + secret(密鑰) Md5後 算出sig Login(); break; case "logout": //同步退出 LoginOut(); break; case "updatepwd": //同步修改密碼 break; } } } } catch (Exception ex) { LogHelper.WriteLog(ex); }}/// <summary>/// 登入/// </summary>private void Login() { Discuz.Toolkit.User user= ds.GetUserInfo(uid); if (user != null) MemberOp.ValidateLogin(user.UserName, user.Password, true);}/// <summary>/// 退出/// </summary>private void LoginOut(){ MemberOp.LoginOut(false);}
以上check_sig()方法裡,主要就是驗證sig是否正確,這個值是通過參數排序後md5出來的,具體過程可以參考方法:Discuz.Forum.Sync.GetUrl()。
注意密鑰apikey、secret、url這幾個值一定要配置正確。至此已實現論壇到網站的同步登入和退出。
DiscuzToolkit線程同步,相信這兩個問題肯定會碰到:
(1)在註冊使用者時,碰到以下異常:當前會話所提交的call_id沒有大於前一次的call_id
(2)註冊使用者時,碰到以下異常:An item with the same key has already been added.
解決辦法:http://www.cnblogs.com/baihmpgy/archive/2012/04/09/2438720.html
解決方案中,有一處線程鎖的問題:
lock (_syncRoot) 可直接用 lock (this)