Discuz!nt整合心得

最近研究了下Discuz!nt的整合,因为是网上找的实例,有个地方的写错了,导致纠结了一整天,这里分享出来.

Discuz!nt提供了整合工具DiscuzToolkit,用于调用Discuz!nt API的一款工具,网上能够很轻松的找到源码,但是项目中需要引用几个DLL,如图

这里附上代码

 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值.

第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验证失败.

这里我说说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整合登录就实现了.

原文地址:https://www.cnblogs.com/tibos/p/5362712.html