最近研究了下Discuz!nt的整合,由於是網上找的實例,有個地方的寫錯了,致使糾結了一成天,這裏分享出來.ajax
Discuz!nt提供了整合工具DiscuzToolkit,用於調用Discuz!nt API的一款工具,網上可以很輕鬆的找到源碼,可是項目中須要引用幾個DLL,如圖數據庫
這裏附上代碼api
1 //登陸 2 protected void btnLogin_Click(object sender, EventArgs e) 3 { 4 string username = un.Value.Trim(); 5 string password = pwd.Value.Trim(); 6 7 string apikey = "3b8ccea63030e2747abf5740b2f57350";//有Discuz後臺管理擴展->通行證設置得到 8 string secret = "7d0a34cfa6f7e2175e03aead1c52fe4c";//同上 9 string url = "http://bbs.oyytv.com/";//你的bbs路徑 10 string cookieDomain = "oyytv.com";//你的域名 11 DiscuzSession ds = new DiscuzSession(apikey, secret, url); 12 int id = ds.GetUserID(username);//根據用戶名獲取用戶ID 13 //用戶名存在 14 if (id > 0) 15 { 16 //取得用戶數據庫中的密碼 17 string dbpassword = ds.GetUserInfo(id).Password; 18 //判斷數據庫中的密碼和輸入的密碼是否一致 19 if (dbpassword == FormsAuthentication.HashPasswordForStoringInConfigFile(password, "MD5").ToLower()) 20 { 21 //輸入密碼正確,則登陸 22 ds.Login(id, dbpassword, true, 10000, cookieDomain); 23 24 Discuz.Config.GeneralConfigInfo config = Discuz.Config.GeneralConfigs.GetConfig(); 25 26 //刪除以前的錯誤登陸信息 27 LoginLogs.DeleteLoginLog(DNTRequest.GetIP()); 28 //根據積分公式刷新用戶總積分 29 UserCredits.UpdateUserCredits(id); 30 //寫入用戶登陸後的cookie 31 ForumUtils.WriteUserCookie(id, Utils.StrToInt(DNTRequest.GetString("expires"), -1), config.Passwordkey, DNTRequest.GetInt("templateid", 0), DNTRequest.GetInt("loginmode", -1)); 32 33 Response.Redirect("http://bbs.oyytv.com"); 34 //更新用戶最後動做,如不須要可不執行 35 //OnlineUsers.UpdateAction(olid, UserAction.Login.ActionID, 0, config.Onlinetimeout); 36 //更新該用戶最後訪問時間 37 // Users.UpdateUserLastvisit(id, DNTRequest.GetIP()); 38 } 39 else 40 { 41 42 } 43 } 44 else 45 { 46 47 } 48 49 }
這裏有幾個存在誤解的地方跨域
整合,由於Discuz!nt是用cookie來保存用戶狀態,經過設置cookie的Domain來進行子站間的跨域,這裏整合說的統一登陸,註冊...,只是針對於子站間的跨域,就是說將一個論壇,包含在你現有系統上緩存
代碼第10行,設置的其實就是Domain值.cookie
第22行 ds.Login(id, dbpassword, true, 10000, cookieDomain);併發
1 /// <summary> 2 /// 登陸 3 /// </summary> 4 /// <param name="uid"></param> 5 /// <param name="password"></param> 6 /// <param name="isMD5Passwd"></param> 7 /// <param name="expires"></param> 8 /// <param name="cookieDomain"></param> 9 public void Login(int uid, string password, bool isMD5Passwd, int expires, string cookieDomain) 10 { 11 User user = GetUserInfo(uid); 12 HttpCookie cookie = new HttpCookie("dnt"); 13 cookie.Values["userid"] = user.UId.ToString(); 14 cookie.Values["password"] = EncodePassword(password, isMD5Passwd); 15 cookie.Values["avatar"] = HttpUtility.UrlEncode(user.Avatar.ToString()); 16 cookie.Values["tpp"] = user.Tpp.ToString(); 17 cookie.Values["ppp"] = user.Ppp.ToString(); 18 cookie.Values["invisible"] = user.Invisible.ToString(); 19 cookie.Values["referer"] = "index.aspx"; 20 cookie.Values["expires"] = expires.ToString(); 21 if (expires > 0) 22 { 23 cookie.Expires = DateTime.Now.AddMinutes(expires); 24 } 25 cookie.Domain = cookieDomain; 26 cookie.Path = "/"; 27 HttpContext.Current.Response.AppendCookie(cookie); 28 }
這裏的登陸只是存一個子站間能夠互相訪問的cookie而已,要注意的是22行的密碼,應該保存加密後的密碼而不是明文密碼,不然會致使你存的cookie在discuz!nt驗證失敗.ide
這裏我說說discuz!nt的驗證方式,全部頁面都繼承於PageBase,在它的構造函數裏面會獲取用戶信息,來判斷用戶是不是遊客,仍是普通用戶,這裏的判斷標識是以userid來判斷,-1表示遊客函數
1 public PageBase() 2 { 3 if (recordPageView) 4 PageViewStatistic(pagename); 5 6 config = GeneralConfigs.GetConfig(); 7 if (SpacePluginProvider.GetInstance() == null) 8 config.Enablespace = 0; 9 if (AlbumPluginProvider.GetInstance() == null) 10 config.Enablealbum = 0; 11 if (MallPluginProvider.GetInstance() == null) 12 config.Enablemall = 0; 13 14 LoadUrlConfig(); 15 userid = Utils.StrToInt(ForumUtils.GetCookie("userid"), -1); 16 //清空當前頁面查詢統計 17 #if DEBUG 18 Discuz.Data.DbHelper.QueryCount = 0; 19 Discuz.Data.DbHelper.QueryDetail = ""; 20 #endif 21 // 若是啓用遊客頁面緩存,則對遊客輸出緩存頁 22 if (userid == -1 && config.Guestcachepagetimeout > 0 && GetUserCachePage(pagename)) 23 return; 24 25 AddMetaInfo(config.Seokeywords, config.Seodescription, config.Seohead); 26 27 if (config.Nocacheheaders == 1) 28 { 29 System.Web.HttpContext.Current.Response.BufferOutput = false; 30 System.Web.HttpContext.Current.Response.ExpiresAbsolute = DateTime.Now.AddDays(-1); 31 System.Web.HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddDays(-1)); 32 System.Web.HttpContext.Current.Response.Expires = 0; 33 System.Web.HttpContext.Current.Response.CacheControl = "no-cache"; 34 System.Web.HttpContext.Current.Response.Cache.SetNoStore(); 35 } 36 37 //當爲forumlist.aspx或forumindex.aspx,可能出如今線併發問題,這時系統會延時2秒 38 if ((pagename != "forumlist.aspx") && (pagename != "forumindex.aspx")) 39 oluserinfo = OnlineUsers.UpdateInfo(config.Passwordkey, config.Onlinetimeout); 40 else 41 { 42 try 43 { 44 oluserinfo = OnlineUsers.UpdateInfo(config.Passwordkey, config.Onlinetimeout); 45 } 46 catch 47 { 48 System.Threading.Thread.Sleep(2000); 49 oluserinfo = OnlineUsers.UpdateInfo(config.Passwordkey, config.Onlinetimeout); 50 } 51 }
代碼15行,先獲取用戶id,這裏是從cookie裏面獲取的,而後再根據id,pwd獲取用戶信息(代碼44行).工具
這裏咱們看看UpdateInfo函數,代碼以下:
1 /// <summary> 2 /// 用戶在線信息維護。判斷當前用戶的身份(會員仍是遊客),是否在在線列表中存在,若是存在則更新會員的當前動,不存在則創建. 3 /// </summary> 4 /// <param name="passwordkey">用戶密碼</param 5 /// <param name="timeout">在線超時時間</param> 6 public static OnlineUserInfo UpdateInfo(string passwordkey, int timeout) 7 { 8 return UpdateInfo(passwordkey, timeout, -1, ""); 9 }
在這裏,它又重載了一次,重載代碼以下:
1 /// <summary> 2 /// 用戶在線信息維護。判斷當前用戶的身份(會員仍是遊客),是否在在線列表中存在,若是存在則更新會員的當前動,不存在則創建. 3 /// </summary> 4 /// <param name="passwordkey">論壇passwordkey</param> 5 /// <param name="timeout">在線超時時間</param> 6 /// <param name="passwd">用戶密碼</param> 7 public static OnlineUserInfo UpdateInfo(string passwordkey, int timeout, int uid, string passwd) 8 { 9 lock (SynObject) 10 { 11 OnlineUserInfo onlineuser = new OnlineUserInfo(); 12 string ip = DNTRequest.GetIP(); 13 int userid = TypeConverter.StrToInt(ForumUtils.GetCookie("userid"), uid); 14 string password = (Utils.StrIsNullOrEmpty(passwd) ? ForumUtils.GetCookiePassword(passwordkey) : ForumUtils.GetCookiePassword(passwd, passwordkey)); 15 16 // 若是密碼非Base64編碼字符串則懷疑被非法篡改, 直接置身份爲遊客 17 if (password.Length == 0 || !Utils.IsBase64String(password)) 18 userid = -1; 19 20 if (userid != -1) 21 { 22 onlineuser = GetOnlineUser(userid, password); 23 24 //更新流量統計 25 if (!DNTRequest.GetPageName().EndsWith("ajax.aspx") && GeneralConfigs.GetConfig().Statstatus == 1) 26 Stats.UpdateStatCount(false, onlineuser != null); 27 28 if (onlineuser != null) 29 { 30 if (onlineuser.Ip != ip) 31 { 32 UpdateIP(onlineuser.Olid, ip); 33 onlineuser.Ip = ip; 34 return onlineuser; 35 } 36 } 37 else 38 { 39 // 判斷密碼是否正確 40 userid = Users.CheckPassword(userid, password, false); 41 if (userid != -1) 42 { 43 Discuz.Data.OnlineUsers.DeleteRowsByIP(ip); 44 CheckIp(ip); 45 return CreateUser(userid, timeout); 46 } 47 else 48 { 49 CheckIp(ip); 50 // 如密碼錯誤則在在線表中建立遊客 51 onlineuser = GetOnlineUserByIP(-1, ip); 52 if (onlineuser == null) 53 return CreateGuestUser(timeout); 54 } 55 } 56 } 57 else 58 { 59 onlineuser = GetOnlineUserByIP(-1, ip); 60 //更新流量統計 61 if (!DNTRequest.GetPageName().EndsWith("ajax.aspx") && GeneralConfigs.GetConfig().Statstatus == 1) 62 Stats.UpdateStatCount(true, onlineuser != null); 63 64 if (onlineuser == null) 65 return CreateGuestUser(timeout); 66 } 67 68 //onlineuser.Lastupdatetime = Utils.GetDateTime(); 爲了客戶端可以登陸註釋此句,若有問題再修改。 69 return onlineuser; 70 } 71 }
在這塊,會產生極大的誤解,由於前文已經說過,-1是判斷是遊客的userid,然而它直接將用戶id賦值爲-1,會讓我在看到第一個函數時,就覺得它要獲取的是遊客信息,致使後面登陸失敗,當跳入到這個方法後(13行),我才發現它又重新在cookie裏面獲取了用戶id,
這裏的密碼有個小細節
/// <summary> /// 返回論壇用戶密碼cookie明文 /// </summary> /// <param name="key">密鑰</param> /// <returns></returns> public static string GetCookiePassword(string key) { return DES.Decode(GetCookie("password"), key).Trim(); }
返回的是密碼明文,也就是我最開始說的那個密碼要保存加密後的,Discuz!nt會將你保存在cookie裏的密碼解密,它的實現方式是這樣的,先將 123456用md5加密成密文,再將密文跟passwordkey,混合加密,而後把這段存入cookie的pwd,Discuz!nt再將cookie裏
的pwd取出,解密,根據uderid和pwd,獲取用戶信息.
到這裏Discuz!nt整合登陸就實現了.