mvc3和dz nt v3.6完美跨域登陆整合解析

 

一、关于dz nt,我要说!

         最近由于工作需要,开发了一套企业内网管理系统。领导想要加上一个论坛,自己做工期太长,况且做出来的也不一定比得上市面上成熟的一些论坛产品(国内如风讯,动网,dz等)。So领导决定采用dz nt v3.60整合到现有企业内网管理系统中,何况 dz nt v3.60刚开源。理论上讲虽然没做过,但有源码好像怎么整合没问题。也许是这样的,往往理想很丰满,现实很骨感!

   对于 dz nt我真不知道怎么说,要形容的话,用“鸡肋”吧!或许更贴切些,nt版本感觉完全是在照顾MS的面子,性能不如PHP(不过也是,康盛主打产品就不是nt.),官方论坛没有提供相关服务。不说其他,单说那些OpenAPI(快要崩溃掉,什么BT API啊。。。。),官方提供的示例源码我看了三遍愣是没完全看懂嘛意思,怎么用(说到这真是崩溃,不知道是我智商低还是,唉那不说了,我知道园内有康盛的大牛。)?还有官方论坛提供的那些所谓的“万能,深度,跨域”整合,全是胡闹(我基本都测试了)。好了,或许我说他不好,不能代表他不好。大家请看:

官方API链接:http://nt.discuz.net/showtopic-142924.html

用户创建对话:image

好吧,不再牢骚了,言归正传。说这么多,我更想说的是:

  1. OpenAPI应该是简洁明了,那怕你没有相关文档,你也能让调用他的人明白这个方法是干什么的,我怎么用,需要传那些参数?
  2. OpenAPI应该是描述调用环境和提供测试DEMO的。

   以上不是不是本文的重点,重点在下面。

二、dz nt 跨域完美整合

  1. 背景:企业内网管理系统(A)+dz nt v3.60(B)跨域整合,实现由A到B自动登陆,注册,退出,修改等功能。由B到A自动登陆,用户可以单独登陆A系统或者B论坛。
  2. 整合思路:

             2.1 通过UCenter来整合第三方应用程序和康盛的其他产品,如图:

     image

    关于此方案,一方面工期原因,一方面运行环境要求(UCenter需要运行mysql数据库,我们服务器不允许装,而且整个整合方案需要配置,开发周期也会比较长),所以我们最终放弃此方案。不过,我见过成功的案例(郑州打折网),整合了自己开发的应用程序,dz X系列论坛和新浪微薄。若有感兴趣的同学可以自己试下,网上有不少相关资料见此博客,官方亦提供不少相关资料。

       2.2 cookie验证

    说到这里,不得不提下dz nt的验证机制,他是基于cookie来判断的,使用论坛后台登录和前台并行确认机制,您必须正确登录前台后才可以访问后台并进行登录操作。

image 

    所以我的整合思路是,其一在A程序里模拟写入cookie通过超链接自动跳转论坛登陆。其二在B论坛中新增跳转页面,从A程序里传入必要参数到B论坛跳转页面,在page_load中写入cookie通过验证,自动登陆论坛。

  dz nt安装有三种方式,因为不同的安装方式在写cookie的时候会有些不同。

     dz nt安装方式有三种http://nt.discuz.net/showtopic-128292.html

1.根目录安装
      根目录安装是最简单也是稳定系数最高的安装和使用方式,为我们的推荐方式。论坛配置项不需要做任何调整,只需要将站点程序(安装包upload_files目录内的所有文件)上传至站点根目录下就可以运行install/index.aspx开始安装了。

2.虚拟目录安装
       由于Discuz!NT拥有能大幅优化搜索引擎友好度的页面伪静态功能,所以如果论坛程序不是安装在根目录下,那么进行安装过程之前将不得不手工的修改论坛的配置节点以适应虚拟目录路径。

打开DNT.config,将<forumpath>/</forumpath>修改为<forumpath>/[您的虚拟目录名称]/</forumpath>
然后就可以运行install/index.aspx开始安装了。

3.子目录安装
      因为很多站点是将论坛整合到自己的站点,但是因为某种原因,不能以虚拟目录的形式存在,则将论坛程序放置在主站点的目录下,称为子目录。

官方有详细的图文教程,怎么安装我不在细说,我只讲下我通过这三种方式的一些教训。

讲之前我先介绍下配置环境:

环境:A系统是做负载均衡,B论坛没有做,WIN2008+IIS7.5+MVC3(即A系统)+MSSQL2008。

    以上是我们的整合环境,第一种根目录安装也是我最终采用的方式。虚拟目录安装和子目录安装总会出现各种各样的问题,时间紧迫也没有追根溯源。比如:在虚拟目录下配置后,运行出错,必须要建应用程序?在子目录下安装,运行后只在论坛首页,其他链接无效?如果以上那位同学做过类似配置或知其原因,请留言告知,非常感谢!

最后我们采用的根目录安装配合子域名发布,如A程序的域名为www.a.com,那B论坛的域名为www.bbs.a.com。论坛安装后好,需要登陆论坛在后台——扩展添加相应整合的程序的一些配置,官方有教程,不细说。

  •    2.2.1 接下去如第一种cookie验证思路,在A程序中模拟写入cookie,进行校验。这种思路验证时遇到一个问题,从A程序跳转到B论坛总是跳转不过去,不能自动登陆。这个问题困扰我好几天,最后才弄清问题原因在Domain,A系统的域是a.com,B论坛的域是bbs.a.com,就是cookie在二级域名可以写到一级域名中,一级域名却不能写到二级域名中,简单说父域名不能写到子域名中。这样就造成了,论坛在验证时我A系统跳转到论坛时所取的cookie Domain就不一样,根本通不过校验。如果两个应用程序要进行双向自动登陆跳转,必须保证:
    1. 持共用用户库
    2. 验证机制一样
    3. 验证内容一样
    4. 验证同一来源,要从一个domian中取cookie来验证。

所以,由于论坛域名是A系统子域名,我要在论坛登陆时改变其cookie域和A系统一样,并且保存cookie方法一致,内容一样才可以。

虽然有源码。但是,要我在短短几天理解透彻dz nt的整个验证机制及登陆过程并修改,难度不小,特别是遇到dz nt那BT的模版机制,更让人抓狂。如图:

image

 

 

 

 

 

截取其中片断。而且就算我理解了他的验证机制,模版机制和登陆过程,我还要在A系统中模拟Cookie写入,虽然有接口,但需要模拟环境。总是不是少引用,就是方法有问题,整个一个乱字了得!所以,我放弃,采用第二cookie验证思路。

  • 2.2.2 采用在B论坛中增加跳转页面,从A系统传入参数,在跳转页面写入Cookie进行验证登陆。用论坛现有的环境,论坛现有的方法,不需要再重新搭建。只需要几行代码搞定MVC3应用程序与论坛完美整合。因为是牵涉到公司项目,不便提供源码,敬请见谅!以下是核心代码:

B论坛中

   1:  using System;
   2:  using System.Collections;
   3:  using System.Configuration;
   4:  using System.Data;
   5:  using System.Web;
   6:  using System.Web.Security;
   7:  using System.Web.UI;
   8:  using System.Web.UI.HtmlControls;
   9:  using System.Web.UI.WebControls;
  10:  using System.Web.UI.WebControls.WebParts;
  11:  using System.Security.Cryptography;
  12:  using System.IO;
  13:   
  14:  using Discuz.Common;
  15:  using Discuz.Forum;
  16:  using Discuz.Config;
  17:  using Discuz.Entity;
  18:  using System.Text;
  19:   
  20:   protected void Page_Load(object sender, EventArgs e)
  21:          {
  22:              string username = string.Empty;
  23:              string pwd = string.Empty;
  24:              if (Request.QueryString["un"] != null)
  25:                  username = decode(Request.QueryString["UN"].ToString());//加密后的用户名
  26:              if (Request.QueryString["pwd"] != null)
  27:                  pwd = decode(Request.QueryString["pwd"].ToString());//加密后的密码
  28:              try
  29:              {
  30:                  Discuz.Config.GeneralConfigInfo config = Discuz.Config.GeneralConfigs.GetConfig();
  31:                  int uid = Users.GetUserId(username);
  32:                  if (uid == -1)
  33:                  {
  34:                      Response.Redirect("Http://www.XXXX.com");
  35:                      return;
  36:                  }
  37:   
  38:                  //删除之前的错误登录信息
  39:                  LoginLogs.DeleteLoginLog(DNTRequest.GetIP());
  40:                  //根据积分公式刷新用户总积分
  41:                  UserCredits.UpdateUserCredits(uid);
  42:                  //写入用户登录后的cookie
  43:                  ForumUtils.WriteUserCookie(uid, Utils.StrToInt(DNTRequest.GetString("expires"), -1), config.Passwordkey, DNTRequest.GetInt("templateid", 0), DNTRequest.GetInt("loginmode", -1));
  44:                  //更新用户最后动作,如不需要可不执行
  45:                  //OnlineUsers.UpdateAction(olid, UserAction.Login.ActionID, 0, config.Onlinetimeout);
  46:                  //更新该用户最后访问时间
  47:                  Users.UpdateUserCreditsAndVisit(uid, DNTRequest.GetIP());
  48:                  Response.Redirect("index.aspx");
  49:              }
  50:              catch(Exception ex)
  51:              {
  52:                  throw ex;
  53:              }
  54:   
  55:          }
  56:          //字符串加密   
  57:          private static string encode(string strText)
  58:          {
  59:              Byte[] Iv64 = { 11, 22, 33, 44, 55, 66, 77, 88 };
  60:              Byte[] byKey64 = { 10, 20, 30, 40, 50, 60, 70, 80 };
  61:              try
  62:              {
  63:                  DESCryptoServiceProvider des = new DESCryptoServiceProvider();
  64:                  Byte[] inputByteArray = Encoding.UTF8.GetBytes(strText);
  65:                  MemoryStream ms = new MemoryStream();
  66:                  CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey64, Iv64), CryptoStreamMode.Write);
  67:                  cs.Write(inputByteArray, 0, inputByteArray.Length);
  68:                  cs.FlushFinalBlock();
  69:                  return Convert.ToBase64String(ms.ToArray());
  70:              }
  71:              catch (Exception ex)
  72:              {
  73:                  return ex.Message;
  74:              }
  75:          }
  76:          //字符串解密   
  77:          private static string decode(string strText)
  78:          {
  79:              Byte[] Iv64 = { 11, 22, 33, 44, 55, 66, 77, 88 };
  80:              Byte[] byKey64 = { 10, 20, 30, 40, 50, 60, 70, 80 };
  81:              Byte[] inputByteArray = new byte[strText.Length];
  82:              try
  83:              {
  84:                  DESCryptoServiceProvider des = new DESCryptoServiceProvider();
  85:                  inputByteArray = Convert.FromBase64String(strText);
  86:                  MemoryStream ms = new MemoryStream();
  87:                  CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey64, Iv64), CryptoStreamMode.Write);
  88:                  cs.Write(inputByteArray, 0, inputByteArray.Length);
  89:                  cs.FlushFinalBlock();
  90:                  System.Text.Encoding encoding = System.Text.Encoding.UTF8;
  91:                  return encoding.GetString(ms.ToArray());
  92:              }
  93:              catch (Exception ex)
  94:              {
  95:                  return ex.Message;
  96:              }
  97:          }

A程序中,就是通过URL传参就可以了.

修改时间:2012-2-11,以上整合dz nt 版本为Discuz!NT 3.6.711!

三、结束  至此,MVC3应用程序和dz nt论坛完美整合,跨域访问结束,如果本文对您有帮助,或您有其他想法请留言,交流!

打个广告:Thinkeer 网是一个IT 技术类相关资料分享的专业网站,致力于打造一个“自由,分享,交流”的技术平台,供程序员学习,交流!
使命:I Can Help You!

PS:本文由于个人技术经验有限,若有纰漏或错误之处敬请谅解。分享(Share),自由(Free),交流(Communicate)的学术氛围,技术才能得以提升!

作   者:lonely_rain
出   处:http://www.cnblogs.com/lonely_rain/
个人站:  http://www.thinkeer.com/
欢迎任何形式的转载,但请务必注明出处。

posted @ 2012-02-07 01:22  lonely_rain  阅读(2992)  评论(3编辑  收藏  举报