.net mvc通过ucenter和 discuz的整合,nopcommerce ucenter 插件的方式实现

discuz无疑是目前市面上最好的论坛之一,对于大多数公司来说,用discuz搭建一个论坛肯定是最节约成本的选择,然而我们的会员想要和discuz进行整合的话,只有两种荀泽,一种直接选用discuz的数据库的用户表作为自己系统的用户表(这种不现实,我如果是mssql,或者是oricle怎么办呢?),第二种就是使用discuz为了解决大家这中需求而提出的ucenter技术,目前小米论坛就是采用的这种技术,下面我就为大家介绍一下.net下使用ucenter的注意细节。

首先引入的第三方已经开发好的ucenter sdk,其原理在其主页文章http://www.dozer.cc/2011/01/ucenter-api-in-depth-1st/

下面我介绍在nopcommerce中使用ucenter的步奏

第一步:你要得到和UCenter进行通信的类库,作者的主页有原始类库http://www.dozer.cc/2011/05/ucenter-api-for-net-on-codeplex/,是asp.net 4.0版的。

第二步,你在你的asp.net项目中引用该类库,引用类库的时候,Browse到dll就行,没有必要把整个项目原代码添加到你的解决方案中。
这个类库有两个重点的文件夹需要注意:DS.Web.UCenter.Api与DS.Web.UCenter.Client,
其中DS.Web.UCenter.Api用于响应由UCenter中心发出的通知消息;
然后DS.Web.UCenter.Client用于本地向UCenter发送消息;

第三步,你需要一个响应通知的页面了,这里为了尊重原作者,我们相应地址的倒数第二层一定要是api,所以我们可以注册一个路由,让该路由的倒数第二层为api

 protected override void RegisterPluginRoutes(RouteCollection routes)
        {
            RegisterPluginRoutesAdmin(routes, "UCenter");

            routes.MapRoute("apiuc",
               "api/uc",
               new { controller = "UCenterOpenApi", action = "OpenApi" },
               new[] { Constants.ControllersNamespace });

        }    

这样子我们就可以通过 http://localhost:305/api/uc 访问到指定控制器下的方法了,

接下来我们就要写UCenterOpenApiController控制器下的OpenApi方法了,代码如下

 public UCenterOpenApiController(UcApiService ucApiService,
            HttpSessionStateBase httpSession,
            UCenterSetting uCenterSetting){
            this._ucApiService = ucApiService;
            this._httpSession = httpSession;
            this._uCenterSetting = uCenterSetting;
 } 

public ActionResult OpenApi() {
            _ucApiService.ProcessRequest(System.Web.HttpContext.Current);
            return Content("");
  }

这段代码的意思就是依赖注入 UcApiService服务,调用UcApiService的PR方法,我想聪明的你一定猜到UcApiService一定是继承了.net中的IHttpHandler接口才能条用PR方法的对吧,

没错,你猜的很正确,下面看一下UcApiService的代码

  public class UcApiService : UcApiBase
    {
        #region Fields
        /// <summary>
        /// 认证服务
        /// </summary>
        private IAuthenticationService _authenticationService;

        //....字段略

     #region 同步登陆
        /// <summary>
        /// 同步登陆
        /// </summary>
        /// <param name="uid">uid</param>
        /// <returns>ApiReturn</returns>
        public override ApiReturn SynLogin(int uid)
        {
            //IUcClient client = new UcClient();
            var user = _uclient.UserInfo(uid);
            if (user != null && user.Success)
            {
                Customer customer = GetNopCustomer(user);
                if (customer != null)
                    _authenticationService.SignIn(customer, true);
                else
                {
                    customer = new Customer
                    {
                        CustomerGuid = Guid.NewGuid(),
                        Email = user.Mail,
                        Username = user.UserName,
                        Password = new Random().Next(100000).ToString(),
                        VendorId = 0,
                        Active = true,
                        CreatedOnUtc = DateTime.UtcNow,
                        LastActivityDateUtc = DateTime.UtcNow,
                    };
                    _customerService.InsertCustomer(customer);
                    //角色
                    _genericAttributeService.SaveAttribute(customer, SystemCustomerAttributeNames.FirstName, user.UserName);
                    //add to ‘Registered‘ role
                    var registeredRole = _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered);
                    if (registeredRole == null)
                        throw new NopException("‘Registered‘ role could not be loaded");
                    customer.CustomerRoles.Add(registeredRole);

                    //Add reward points for customer registration (if enabled)
                    if (_rewardPointsSettings.Enabled &&
                        _rewardPointsSettings.PointsForRegistration > 0)
                        customer.AddRewardPointsHistoryEntry(_rewardPointsSettings.PointsForRegistration, _localizationService.GetResource("RewardPoints.Message.EarnedForRegistration"));

                    _customerService.UpdateCustomer(customer);
                    _authenticationService.SignIn(customer, true);
                }
                return ApiReturn.Success;
            }
            else
                return ApiReturn.Failed;

        }
        #endregion

   //其他的实现略

}    

可以看出我们的自定义UcApiService继承了 一开始提到的sdk中的UcApiBase,而UcApiBase实现了IHttpHandler和IRequiresSessionState接口,所以在我们的方法中可以直接调用

UcApiService的PR方法。UcApiBase鸡肋中还有好多的方法等待实现,我就不一一列出了,具体可以自己去查看。我们就看这个同步登陆的方法,大体意思就是ucenter下属有其它站点登陆了,我们只要在这个方法中查找的这个用户,并且设置他在本站的状态也为登陆状态,说白了就是授权用户登录本站,只是不需要用户再次的输入账号密码而已。

第四步,上一步是ucenter通知我们有用户从其他站登录了,要求我们这里也登录,那么如果有会员通过我们这个站登录了,我们也是要告诉ucenter的,所以我们这里需要在会员登录成功的情况下,告诉ucenter,这个会员已经成功登录了,你可以让他在其他站也进行登录,具体的实现就是在生成用户凭证的时候调用sdk中IUcClient中的UserLogin方法,如果登录成功,改方法会返回一段js脚本,我们只需要把这段js脚本放到页面上即可。具体代码如下

    /// <summary>
    /// ucenter自定义 登陆认证和 退出认证 实现
    /// </summary>
    public class NopUiUcenterAuthenticationService : INopUiUcenterAuthenticationService
    {
        #region Fields
        /// <summary>
        /// HttpContextBase
        /// </summary>
        private HttpContextBase _httpContext;
        //private readonly ICustomerService _customerService;
        /// <summary>
        /// CustomerSettings
        /// </summary>
        private readonly CustomerSettings _customerSettings;
        /// <summary>
        /// UCenterSetting
        /// </summary>
        private UCenterSetting _uCenterSetting;
        /// <summary>
        /// IUcClient
        /// </summary>
        private IUcClient _uclient;
        /// <summary>
        /// 日志服务
        /// </summary>
        private ILogger _logger;
        // private ICustomerActivityService _customerActivityService;
        #endregion

        #region Ctor
        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="httpContext">HttpContextBase</param>
        /// <param name="customerSettings">CustomerSettings</param>
        /// <param name="_uCenterSetting">UCenterSetting</param>
        /// <param name="_uclient">IUcClient</param>
        /// <param name="_logger">日志服务</param>
        public NopUiUcenterAuthenticationService(HttpContextBase httpContext,
            // ICustomerService customerService,
            CustomerSettings customerSettings,
            UCenterSetting _uCenterSetting,
            IUcClient _uclient, ILogger _logger
            //  ICustomerActivityService _customerActivityService
            )
        {
            this._httpContext = httpContext;
            // this._customerService = customerService;
            this._customerSettings = customerSettings;
            this._uCenterSetting = _uCenterSetting;
            this._uclient = _uclient;
            this._logger = _logger;
            //this._customerActivityService = _customerActivityService;
        }
        #endregion

        #region Methods
        /// <summary>
        /// 认证
        /// </summary>
        /// <param name="customer">Customer</param>
        public void SignIn(Customer customer)
        {
            if (!_uCenterSetting.AvailableUcenter || _httpContext.Request.Form["Password"] == null)
                return;
            //同步登陆
            try
            {
                string Password = _httpContext.Request.Form["Password"].ToString().Trim();
                //IUcClient client = new UcClient();
                UcUserLogin user = null;
                if (_customerSettings.UsernamesEnabled)
                    user = _uclient.UserLogin(customer.Username, Password);//登陆
                else
                    user = _uclient.UserLogin(customer.Email, Password, LoginMethod.Mail);//登陆
                if (user != null && user.Success)//判断是否登陆成功
                {
                    switch (user.Result)
                    {
                        case LoginResult.Success:
                            //保存到会话中
                            // _customerActivityService.InsertActivity("uCenter", "客户从本地登陆,并且成功同步到uCenter中", customer);
                            _httpContext.Session[Constants.UcenterLoginSessionKey] = _uclient.UserSynlogin(user.Uid);
                            break;
                        case LoginResult.NotExist:
                            //用户不存在 那么就注册到ucenter吧
                            //_logger
                            var registerResult = _uclient.UserRegister(customer.Username, Password, customer.Email);
                            if (registerResult.Result == RegisterResult.Success)
                            {
                                // _customerActivityService.InsertActivity("uCenter", "客户在本地存在,但是在ucenter中不存在,此处注册此用户到uCenter中成功", customer);
                                _httpContext.Session[Constants.UcenterLoginSessionKey] = _uclient.UserSynlogin(registerResult.Uid);
                            }
                            else
                                _logger.Error(registerResult.Result.ToString() + "---同步登陆到uCenter时异常,描述:本地已经存在的用户但是ucenter中没有,试图向ucenter中注册此用户的时候,注册失败", null, customer);
                            break;
                        case LoginResult.PassWordError:
                            //密码不对,那就把用户中心的密码改成和本商城中一样的呗
                            var s = _uclient.UserEdit(customer.Username, null, Password, null, true);
                            if (s.Result == UserEditResult.Success)
                            {
                                //_customerActivityService.InsertActivity("uCenter", "客户在本地和ucenter中的密码不一样,但是以本商城的密码为主,所以到ucenter中修改此用户的登陆密码,成功", customer);
                                _httpContext.Session[Constants.UcenterLoginSessionKey] = _uclient.UserSynlogin(user.Uid);
                            }
                            break;
                        case LoginResult.QuestionError:
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    _logger.Error("ucteter同步异常,请查看ucenter配置页的配置是否正确", null, customer);
                }
            }
            catch (Exception ex)
            {

                _logger.Error("ucteter同步异常", ex, customer);
            }
        }

        /// <summary>
        /// 取消认证
        /// </summary>
        public void SignOut()
        {
            if (_uCenterSetting.AvailableUcenter)
                _httpContext.Session[Constants.UcenterLoginOutSessionKey] = _uclient.UserSynLogout();
        }
        #endregion
    }

我们把返回的js脚本方法 会话中,再跳转的时候把这段脚本打到页面上,再删除这段会话即可。

第五步,这步是写配置信息,因为原始类库的配置信息都写到它自己的App.config中去了,但是我这里把作者从配置文件读出配置的方式改成从数据库读取了,配置信息如下图所示

第六步,检查本地服务器和UCenter服务器是否能正常通信

第七步,去UCenter添加此应用,具体怎么填的图片如下:

填写完以后到列表页面看到如下所示,则表示通信成功

 现在我们就可以测试是否可以正常同步了。

打开discuz登录一个用户后,再到我们商城中会发现,改用户已经登录了商城,就算该用户在我们商城不存在,我们也会在同步的时候自动注册该用户。

 

到此 基本上从三美到 discuz 的同步基本完成。

但是,我不知道discuz是故意的还是无意的,这其中一共有三个问题

  1. 我从discuz登录用户,却无法同步 到三美商城。
  2. 从三美商城注册的用户,无法即时同步到discuz,需要在discuz登录一下,以后就可以同步了,及需要激活!
  3. 从discuz注册的用户,无法即时同步 到三美商城。

要想解决这三个问题,都得要从discuz入手,首先解决第一个问题:

  打开discuz安装路径下 \bbs\uc_client\data\cache\apps.php:

你会发现只有discuz x 本身应用,所以就不会同步登陆,我也不知道什么原因造成。

我们把三美的应用也加进去即可解决从discuz登录不同步到三美商城的问题

接着解决第二个问题:

第二个问题产生的主要原因是,我们注册的用户,同步登陆的时候,discuz并没有把这个用户添加到他的用户表里面,而是用户激活后才添加到他自己的用户表,找到原因后就很好解决了,

我们只需要在用户同步登陆的时候把用户添加到用户表中即可,

修改文件:/api/uc.php

    function synlogin($get, $post) {
        global $_G;

        if(!API_SYNLOGIN) {
            return API_RETURN_FORBIDDEN;
        }

        header(‘P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"‘);

        $cookietime = 31536000;
        $uid = intval($get[‘uid‘]);
        if(($member = getuserbyuid($uid, 1))) {
            dsetcookie(‘auth‘, authcode("$member[password]\t$member[uid]", ‘ENCODE‘), $cookietime);
        }else{
             $query = DB::query("SELECT email FROM ".DB::table(‘ucenter_members‘)." WHERE uid=‘$uid‘");
             if($a = DB::fetch($query)){
                 $email = $a[‘email‘];
             }else{
                 $email = $get[‘email‘];
             }
            $username = $get[‘username‘];
            $password = md5(time().rand(100000, 999999));
            //$email = $get[‘email‘];
            $ip = $_SERVER[‘REMOTE_ADDR‘];
            $time = time();
            $userdata = array(
              ‘uid‘ => $uid,
              ‘username‘ => $username,
              ‘password‘ => $password,
              ‘email‘ => $email,
              ‘adminid‘ => 0,
              ‘groupid‘ => 10,
              ‘regdate‘ => $time,
              ‘credits‘ => 0,
              ‘timeoffset‘ => 9999
            );
            DB::insert(‘common_member‘, $userdata);
            $status_data = array(
              ‘uid‘ => $uid,
              ‘regip‘ => $ip,
              ‘lastip‘ => $ip,
              ‘lastvisit‘ => $time,
              ‘lastactivity‘ => $time,
              ‘lastpost‘ => 0,
              ‘lastsendmail‘ => 0,
            );
            DB::insert(‘common_member_status‘, $status_data);
            DB::insert(‘common_member_profile‘, array(‘uid‘ => $uid));
            DB::insert(‘common_member_field_forum‘, array(‘uid‘ => $uid));
            DB::insert(‘common_member_field_home‘, array(‘uid‘ => $uid));
            DB::insert(‘common_member_count‘, array(‘uid‘ => $uid));
            if(($member = getuserbyuid($uid, 1))) {
                dsetcookie(‘auth‘, authcode("$member[password]\t$member[uid]", ‘ENCODE‘), $cookietime);
            }
        }
    }

保存上述代码即可解决第二个问题

下面解决最后一个问题,这个问题其实本质和第二个很相似,只需要在用户注册的时候调用一下登陆方法即可。

具体参考方法见:http://www.discuz.net/thread-2356743-1-1.html

至此 就可以实现商城和discuz的用户同步了,本篇文章是基于 nopcommerce3.5和discuz x3.2的同步解决方案。

时间: 2024-08-01 08:46:32

.net mvc通过ucenter和 discuz的整合,nopcommerce ucenter 插件的方式实现的相关文章

织梦系统与discuz论坛整合方法

如何完成dedecms模板系统与discuz论坛整合呢? 这里的整合指会员信息,会员登陆.退出的同步:论坛信息的引用:等等. 首先,我们先来安装织梦(dedecms)系统. 然后,我们在网站根目录下建一个BBS文件夹,将Discuz_X1.5下面upload文件夹下一切文件上传到BBS外. 第三步,安装discuz论坛 方法为:运行http://网址/bbs/install/进行安装.在安装第二步选择第一个选项选(全新安装 Discuz! X (含 UCenter Server)),后面的数据库

帝国CMS与Ucenter同步通信,会员整合

背景:公司因上市进行项目大整合.一部分项目使用phalcon新框架,一小部分使用帝国CMS,这样就产生了问题:phalcon框架对cookie具有加解密,帝国获取到phalcon的cookie但却无法解密.或许你想到的是将phalcon中得cookie加解密方法移植过去即可,但phalcon是C语言写得框架,框架只提供接口,不提供源码..这个方法over.so使用ucenter同步登陆的方法在帝国中获取相应的用户信息.接下来将介绍如何进行整合. 步骤一.下载帝国CMS和Ucenter同步通信的插

UCenter 与 DIscuz 通信失败的解决方法

问题状况:Discuz 用户无法成功修改头像且帖子中上传的图片无法保存.进入 Discuz 后台检查,一切正常:进入 UCenter 检查后发现在"应用管理"中与 Discuz 论坛的"通信情况"状态为"通信失败". 检查位置如下: 1.Discuz 后台--全局-- UCenter 设置 2.UCenter 后台--应用列表--点击 Discuz 论坛后面的"编辑" 检查内容如下: 1."应用的 URL"

自制MVC框架CRUD操作、列表、分页显示插件介绍

这里涉及到的操作都是引用自Stephen.DALService数据层.数据访问层实现方式在后文中我会仔细的说明,先说明一下数据操作集成的插件. 1).InsertAttribute 用于插入记录. 状态返回值:假定hashtable传递变量名的是context ,那么返回值可通过context[InsertAttribute.ValueKey]得到,推荐返回的是插入的主键ID值,当然这个是由数据层设定的. 有以下属性可进行设置: 属性名 作用 默认值 选项说明 其它说明 Key 映射路径.格式如

Spring Boot 整合 Shiro ,两种方式全总结!

在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot 整合 Shiro 的话题! 一般来说,Spring Security 和 Shiro 的比较如下: Spring Security 是一个重量级的安全管理框架:Shiro 则是一个轻量级的安全管理框架 Spring Security 概念复杂,配置繁琐:Shiro 概念简单.配置简单 Spring

discuz 用户整合 账号整合 ucenter php网站整合discuz用户

引用:https://www.cnblogs.com/kenkofox/archive/2011/09/18/2180649.html 1.登录后台管理.(在论坛中,用创建论坛的admin账号登陆,然后点“管理中心”) 2.添加新应用,填写资料.其实就是“名称”和“密钥”重要一些而已.例如我这里添加的“香芋网” 3.复制生成的配置代码,贴到constants.php中(CodeIgniter),或者使用前引入一个配置,在该配置中贴这些配置代码.   然后,就是使用了:参考developguide

Discuz 3.1 登陆ucenter验证码错误的解决

今天安装LAMP,配置安装discuz3.1还算顺利.遇到discuz ucenter验证码问题供大家参考. 不过discuz中ucenter登陆验证码处显示看不清,复制图片链接到浏览器发现是CCCC,输入验证码提示验证码错误,无法登陆. 感觉我这应该不是网上说的IP动态,缺少文件,目录权限问题,最后发现有个哥们也这个问题. 第一步:vim打开对应的文件:/uc_server/control/admin/seccode.php 第二步:38行找到$code->ttf = 1;修改为$code->

Spring MVC + Spring MongoDB + Querydsl 通过maven整合实例

效果图 一共3个页面:注册页,欢迎页,用户列表页 很简单的例子,主要是为了把流程走通,没有各种验证. 注册页: 欢迎页: 用户列表页: 源码地址 https://github.com/lemonbar/spring-framework-mongodb 参考文档 Spring framework: http://docs.spring.io/spring/docs/4.0.6.RELEASE/spring-framework-reference/htmlsingle/#spring-web Spr

Discuz升级!图片查看插件(支持鼠标缩放、实际大小、旋转、下载)

图片查看是网站中的常用功能,用于展示详细的图片.在discuz图片插件的基础上进行了改造,因此这篇文章主要从以下几个方面来讨论图片查看插件.希望可以帮助到大家,有不对的地方也欢迎大家给以正确的指导. (1)discuz的实现过程及效果 (2)discuz的局限性 (3)discuz的改进步骤 (4)兼容性及最后效果 (5)总结(常见问题) demo示例:http://zyk3.ataw.cn/discuz/index.html 一.discuz的实现过程及效果 点击图片,弹出层有大图,同时有在新