Asp.net 与 UCenter 用户同步之实施过程
在写这篇文章的时候,我还在想,这篇文章也许能给你带来一些收获,但或许会令你更加的迷茫,为什么会这样?
因为:
1、UCenter虽然足够强大,但正为它的强大,它的不少暗箱操作使得我们望而生畏,我们不害怕出错,我们害怕出错时抓不到出错点。
2、同步登录经常会跨平台,跨服务器,跨域,跨数据库等。环境要求比较高,这使得我们需要更多地了解它。
最近公司弄了个团购项目,要求团购的用户和论坛的会员同步起来,以期实现优质会员享受更低折扣等功能。这个项目正是以asp.net开发,当然,在这里要非常感谢同步API的原作者dozer,其原理在其主页文章http://www.dozer.cc/2011/01/ucenter-api-in-depth-1st/
有详细介绍,我这里只简单介绍一下:
UCenter是所有子项目的核心,任何其中某一子应用(包括Discuz论坛)通过向它发送登录,注册,删除,退出等消息,再由UCenter转发到其它的子应用。
,另外我只介绍一下需要重点步骤及需要注意的地方。
第一步,你要得到和UCenter进行通信的类库,作者的主页有原始类库http://www.dozer.cc/2011/05/ucenter-api-for-net-on-codeplex/,是asp.net 4.0版的。我的环境是3.5所以将类库作了一些修改,修改之后的版本在这里/Files/CoreCaiNiao/DS.Web.UCenter.rar。
第二步,你在你的asp.net项目中引用该类库,引用类库的时候,Browse到dll就行,没有必要把整个项目原代码添加到你的解决方案中。
这个类库有两个重点的文件夹需要注意:DS.Web.UCenter.Api与DS.Web.UCenter.Client,
其中DS.Web.UCenter.Api用于响应由UCenter中心发出的通知消息;
然后DS.Web.UCenter.Client用于本地向UCenter发送消息;
第三步,你的asp.net项目需要一个专门向MySql数据库提供操作的类,为了使用本类,还需要安装mysql-connector-net-6.4.3.msi,这个文件可以到官网去下载(上谷歌搜一下),之后,建立用于连接MySql的类。
有人要问和MySql数据库通信的必要性,我得解释一下,UCenter向你的应用发出的通知里,只有UID,要想得到更多的用户信息,唯有和MySql通信。
我这里有一个临时写的,如果你不介意,可以拿去用,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Data; namespace UCenterDB
{
public class MySqlHelper
{
private string connString;
private MySqlConnection conn; public string ConnString {
set
{
connString = value;
conn = new MySqlConnection(this.connString);
}
} public MySqlHelper(string connString) {
this.connString = connString;
conn = new MySqlConnection(this.connString);
} public int ExecuteNonQuery(string query) {
MySqlCommand cmd = createTxtCommand(query);
int result = -1;
try
{
conn.Open();
result = cmd.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
//错误处理过程
}
return result;
} public string ExecuteScalar(string query)
{
MySqlCommand cmd = createTxtCommand(query);
string result = string.Empty;
try
{
conn.Open();
result = cmd.ExecuteScalar().ToString();
conn.Close();
}
catch (Exception ex)
{
//错误处理过程
}
return result;
} public DataTable GetDataTable(string query) {
DataSet ds = new DataSet();
MySqlDataAdapter msda = new MySqlDataAdapter();
msda.SelectCommand = createTxtCommand(query);
msda.Fill(ds);
return ds != null && ds.Tables.Count > 0 ? ds.Tables[0] : null;
} private MySqlCommand createTxtCommand(string query) {
return new MySqlCommand
{
Connection = conn,
CommandText = query,
CommandType = CommandType.Text
};
}
}
}
不过我要提醒一下,为了安全,在主服务器开放MySql对外的帐户权限的时候,仅需要开放select权限就可以了。
第四步,你需要一个响应通知的页面了,这里为了尊重原作者,我在WEB根目录下建立了API文件夹,并在里面建立了一个名为uc.ashx的响应文件。这个页面用于响应UCenter的同步通知。
文件内容如下:
using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using DS.Web.UCenter;
using DS.Web.UCenter.Api;
using System.Collections.Generic;
using UCenterDB; namespace CoreCaiNiao.Web.API
{
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class uc : UcApiBase
{
SiteMemberManager users = TuanGouManager.siteMemberManager;
MySqlHelper msh = new MySqlHelper(DBConfig.ConnStringMySql);
public override ApiReturn DeleteUser(IEnumerable<int> ids)
{
throw new NotImplementedException();
}
public override ApiReturn RenameUser(int uid, string oldUserName, string newUserName)
{
throw new NotImplementedException();
}
public override UcTagReturns GetTag(string tagName)
{
throw new NotImplementedException();
}
public override ApiReturn SynLogin(int uid)
{
SiteMember loginMember = users.GetInfoByUid(uid);
DataTable dt = msh.GetDataTable("select uid,username,password,email,groupid from pre_common_member where uid=" + uid + " limit 0,1");
if (dt == null || dt.Rows.Count < 1)
{
return ApiReturn.Failed;//无法从远端找到,则此用户不存在
}
DataRow dr = dt.Rows[0];
if (loginMember != null) {//从本地库找到,则更新库
loginMember.ULevel = dr[4].ToString().ToNumber();
users.EditInfo();
//以下代码保存会话到浏览器进程
TuanGouManager.userSessionManager.Login(loginMember, UserLoginExpire.NoSave);
return ApiReturn.Success;
}
//本地库没有,则添加到本地库
loginMember = new SiteMember
{
CreateTime = DateTime.Now,
Address = "",
BadAppCount = 0,
CumulateMoney = "",
EditTime = DateTime.Now,
Email = dr[3].ToString(),
GoodAppCount = 0,
Intro = "",
IpAddress = HttpContext.Current.Request.UserHostAddress,
IsLock = 0,
NickName = "",
NormalAppCount = 0,
PickedMoney = "",
RemainMoney = "",
SiteAuthoritys = "",
SiteRole = "",
TrueName = "",
UID = uid,
ULevel = dr[4].ToString().ToNumber(),
UserName = dr[1].ToString(),
UserPass = dr[2].ToString(),
UserQQ = "",
UserSex = "保密",
UserTel = "",
UserType = ",1,"
};
int userId = users.AddNewInfo(loginMember);
loginMember.ID = userId;
//以下代码保存会话到浏览器进程
TuanGouManager.userSessionManager.Login(loginMember, UserLoginExpire.NoSave);
return ApiReturn.Success;
}
public override ApiReturn SynLogout()
{
TuanGouManager.userSessionManager.Logout();
return ApiReturn.Success;
}
public override ApiReturn UpdatePw(string userName, string passWord)
{
throw new NotImplementedException();
}
public override ApiReturn UpdateBadWords(UcBadWords badWords) { throw new NotImplementedException(); }
public override ApiReturn UpdateHosts(UcHosts hosts) { throw new NotImplementedException(); }
public override ApiReturn UpdateApps(UcApps apps) { throw new NotImplementedException(); }
public override ApiReturn UpdateClient(UcClientSetting client) { throw new NotImplementedException(); }
public override ApiReturn UpdateCredit(int uid, int credit, int amount) { throw new NotImplementedException(); }
public override UcCreditSettingReturns GetCreditSettings() { throw new NotImplementedException(); }
public override ApiReturn GetCredit(int uid, int credit) { throw new NotImplementedException(); }
public override ApiReturn UpdateCreditSettings(UcCreditSettings creditSettings) { throw new NotImplementedException(); }
}
}
我的示例代码中,只对同步登录和退出消息作出响应,具体过程中,您可以根据需要作更多的响应.
第五步,这步是写配置信息,因为原始类库的配置信息都写到它自己的App.config中去了,我们需要复制过来到Web.config
在<appSettings>节中,加入以下行:
<!--DZ1.5用户同步-->
<!--客户端版本-->
<add key="UC_CLIENT_VERSION" value="1.5.2"/>
<!--发行时间-->
<add key="UC_CLIENT_RELEASE" value="20101001"/>
<!--API 开关(value类型:True False 默认值:True)-->
<!--是否允许删除用户-->
<add key="API_DELETEUSER" value="True"/>
<!--是否允许重命名用户-->
<add key="API_RENAMEUSER" value="True"/>
<!--是否允许得到标签-->
<add key="API_GETTAG" value="True"/>
<!--是否允许同步登录-->
<add key="API_SYNLOGIN" value="True"/>
<!--是否允许同步登出-->
<add key="API_SYNLOGOUT" value="True"/>
<!--是否允许更改密码-->
<add key="API_UPDATEPW" value="True"/>
<!--是否允许更新关键字-->
<add key="API_UPDATEBADWORDS" value="True"/>
<!--是否允许更新域名解析缓存-->
<add key="API_UPDATEHOSTS" value="True"/>
<!--是否允许更新应用列表-->
<add key="API_UPDATEAPPS" value="True"/>
<!--是否允许更新客户端缓存-->
<add key="API_UPDATECLIENT" value="True"/>
<!--是否允许更新用户积分-->
<add key="API_UPDATECREDIT" value="True"/>
<!--是否允许向UCenter提供积分设置-->
<add key="API_GETCREDITSETTINGS" value="True"/>
<!--是否允许获取用户的某项积分-->
<add key="API_GETCREDIT" value="True"/>
<!--是否允许更新应用积分设置-->
<add key="API_UPDATECREDITSETTINGS" value="True"/>
<!--API 开关结束-->
<!--返回值设置-->
<!--返回成功(默认:1)-->
<add key="API_RETURN_SUCCEED" value="1"/>
<!--返回失败(默认:-1)-->
<add key="API_RETURN_FAILED" value="-1"/>
<!--返回禁用(默认:-2)-->
<add key="API_RETURN_FORBIDDEN" value="-2"/>
<!--返回值设置结束-->
<!--[必填]通信密钥-->
<add key="UC_KEY" value="FD144298AF7E4797A66ACC0C18CXXEA3"/>
<!--[必填]UCenter地址,这个要根据需要变化,例如,http://你的论坛UCENTER地址-->
<add key="UC_API" value="http://bbs.XXX.XXX.com/ucenter" />
<!--[必填]默认编码-->
<add key="UC_CHARSET" value="utf-8"/>
<!--[非必填]UCenter IP-->
<add key="UC_IP" value=""/>
<!--[必填]应用ID-->
<add key="UC_APPID" value="4"/>
这里有三行要改:
倒数第1行:应用ID:UC_APPID
倒数第4行:UCenter地址:UC_API
倒数第5行:通信密钥:UC_KEY
另外,再加上MySqlProviderFactories节
<!--MySql使用-->
<system.data>
<DbProviderFactories>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.4.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
第六步,检查本地服务器和UCenter服务器是否能正常通信(两台服务器互相telnet IP地址 80)
第七步,去UCenter添加此应用,具体怎么填的图片如下:
最后,我祈祷你能通信成功并同步成功。建议先在本地进行DEBUG模式,在uc.ashx文件的SynLogin(int uid)方法及UpdateApps(UcApps apps)处下断点,这样可以查看是否有通知过来,之后再确定问题的根源。
我成功的图片:
最新提醒:
有不少读者反映为什么引用我的UC.ashx后不能直接被编译?这是因为你直接把我的业务逻辑代码也照搬了,实际上
public override ApiReturn SynLogin(int uid)
这个函数是用来做你自己的业务处理的,做完处理后,返回给接口一个成功的信号就行了,形式如同这样:
1 public override ApiReturn SynLogin(int uid)
2 {
3 SiteMember loginMember = users.GetInfoByUid(uid);
4 DataTable dt = msh.GetDataTable("select uid,username,password,email,groupid from pre_common_member where uid=" + uid + " limit 0,1");
5 if (dt == null || dt.Rows.Count < 1)
6 {
7 return ApiReturn.Failed;//无法从远端找到,则此用户不存在
8 }
9 DataRow dr = dt.Rows[0];
10 if (loginMember != null) {//从本地库找到,则更新库
11 loginMember.ULevel = dr[4].ToString().ToNumber();
12 users.EditInfo();
13 TuanGouManager.userSessionManager.Login(loginMember, UserLoginExpire.NoSave);
14 return ApiReturn.Success;
15 }
16
17 //本地库没有,则添加到本地库
18 loginMember = new SiteMember
19 {
20 CreateTime = DateTime.Now,
21 Address = "",
22 BadAppCount = 0,
23 CumulateMoney = "",
24 EditTime = DateTime.Now,
25 Email = dr[3].ToString(),
26 GoodAppCount = 0,
27 Intro = "",
28 IpAddress = HttpContext.Current.Request.UserHostAddress,
29 IsLock = 0,
30 NickName = "",
31 NormalAppCount = 0,
32 PickedMoney = "",
33 RemainMoney = "",
34 SiteAuthoritys = "",
35 SiteRole = "",
36 TrueName = "",
37 UID = uid,
38 ULevel = dr[4].ToString().ToNumber(),
39 UserName = dr[1].ToString(),
40 UserPass = dr[2].ToString(),
41 UserQQ = "",
42 UserSex = "保密",
43 UserTel = "",
44 UserType = ",1,"
45 };
46 int userId = users.AddNewInfo(loginMember);
47 loginMember.ID = userId;
48 TuanGouManager.userSessionManager.Login(loginMember, UserLoginExpire.NoSave);
49 return ApiReturn.Success;
50 }
其中,灰色的部分千万别抄,只是示意代码,绿色的部分是必须要的,作用是向接口表明你已经成功处理登录业务啦。
应朋友要求,特制作DEMO一份,已测试同步成功!用户需要自行安装UCenter及论坛等.UC_Demo.rar
DEMO说明:
1、子应用登录入口:default.aspx
2、注意web.config中的几处不要填错了,通信密钥,应用ID,UCenter地址(最好用域名或映射域名而不要用IP,有时直接用IP无法连接),编码(中文用户名时会用到)
3、该DEMO请在调试状态下进行,方便知道问题所在。在UCenter配置此Demo的新应用时,应该带上端口号,例如http://localhost:28457/
您可以转载本文,但请标明出处:http://www.cnblogs.com/CoreCaiNiao/archive/2011/08/25/2153434.html
Asp.net 与 UCenter 用户同步之实施过程的更多相关文章
- BI实施过程中的工具与服务
成功的BI项目,不仅仅是应用了BI工具软件,还要具备完善的BI服务体系,才能称之为真正成功的商业智能bi项目. 现在的BI(商业智能)比起几年前的ERP一样,成为CIO们关注的焦点.在ERP等基础信息 ...
- 【ASP.NET】UCenter实现多站点同步注册
问题描述 上一篇文章写了[ASP.Net]UCenter实现多站点同步登录退出 在整合论坛的时候,同步注册也是相当必要的一个功能:将论坛注册的用户同步到自己的网站,自己网站注册的用户同步到论坛. 官方 ...
- 【ASP.NET】UCenter实现多站点同步登录退出
利用UCenter实现discuz论坛和应用网站同步登录和退出功能 测试环境:Discuz! X3.2.UCenter 1.6..Net Framework 4.0 进入Discuz 后台的UCent ...
- ucenter 整合同步登录的内部实现原理及thinkphp整合ucenter
1.用户登录discuz,通过logging.php文件中的函数uc_user_login对post过来的数据进行验证,也就是对username和password进行验证.2.如果验证成功,将调用位于 ...
- 网站与phpwind用户同步的方法
搭建了一个个人网站,希望使用phpwind来完成论坛功能.但很快就发现存在用户同步的问题,我的网站已经有了用户管理功能, phpwind论坛也有.因此用户同步注册,登陆和注销是必须要实现的. 网上说可 ...
- Discuz x3 UCenter实现同步登陆原理
1.Discuz x3 的登录页面URL是:/member.php?mod=logging&action=login 2.这个登录页面,登录提交的地址是: <form method=&q ...
- ucenter 整合同步登录的内部实现原理
1.用户登录discuz,通过logging.php文件中的函数uc_user_login对post过来的数据进行验证,也就是对username和password进行验证. 2.如果验证成功,将调用位 ...
- 简单分析ucenter 会员同步登录通信原理
1.用户登录discuz,通过logging.php文件中的函数uc_user_login对post过来的数据进行验证,也就是对username和password进行验证. 2.如果验证成功,将调用位 ...
- 七天学会ASP.NET MVC (四)——用户授权认证问题
小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在第四天的学习中,我们主要了学习如何在MVC中如何实现认证授权等问题,本节主要讲了验证错误时的错误值,客户端验 ...
随机推荐
- 题解-CodeForces835F Roads in the Kingdom
Problem CodeForces-835F 题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值 Solution 首先明确删去环上一点是不会影响树内直径的,所以应当先把 ...
- centos6.8安装httpd后无法访问
1.打开 httpd.conf 将里面的 #ServerName localhost:80 注释去掉 2.修改SELinux状态: 1)/usr/sbin/sestatus -v ##如果S ...
- SIFT+BOW 实现图像检索
原文地址:https://blog.csdn.net/silence2015/article/details/77374910 本文概述 图像检索是图像研究领域中一个重要的话题,广泛应用于医学,电子商 ...
- 开源录屏工具 Best Screen Recording Open Source Software For Windows 2017
OBS Studio OBS (Open Broadcaster Software) - Free and open source software for live streaming and sc ...
- 使用Filezilla搭建FTP服务器
1.FTP over TLS is not enabled, users cannot securely http://blog.sina.com.cn/s/blog_4cd978f90102vtwl ...
- ModelSerializer序列化(Apiview)
url部分: url(r'^book/$',views.book.as_view()),url(r'^books/(\d+)/$', views.bookdetail.as_view(),name=' ...
- java基础编程题练习(一)
1.编程实现用户输入4个整数,按从大到小的顺序排列输出. 思路:将输入的数据存入数组,使用冒泡排序对数组数据进行排序后输出数组 冒泡排序的代码如下: import java.util.Scanner; ...
- HTML中特殊符号的处理
一.写在前面 今天在写页面时记不清大/小于符号该怎么写,于是就想着整理一下方便后面用到! 二.HTML中常用特殊符号的处理 < < 小于号或显示标记 > ...
- oracle数据库定时任务dbms_job的用法详解
本文来源:Ruthless <oracle数据库定时任务dbms_job的用法详解> 一.dbms_job涉及到的知识点 1.创建job: variable jobno number; ...
- Confluence 6 使用电子邮件可见
Confluence 提供了 3 个电子邮件策略,这些策略 Confluence 管理员可以通过管理员控制台(Administration Console)进行配置: 公开(Public):电子邮件地 ...