• 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整合登录就实现了.

  • 相关阅读:
    Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
    zookeeper 是如何保证事务的顺序一致性的?
    什么是 Callable 和 Future?
    MyBatis 实现一对一有几种方式?具体怎么操作的?
    Zookeeper 对节点的 watch监听通知是永久的吗?为什么 不是永久的?
    合同测试你懂什么?
    查看各类环境变量用什么命令?
    我们如何进行跨功能测试?
    怎么查看系统支持的所有信号?
    Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
  • 原文地址:https://www.cnblogs.com/tibos/p/5362712.html
Copyright © 2020-2023  润新知