1. 程式人生 > >Asp.net 與 UCenter 用戶同步之實施過程

Asp.net 與 UCenter 用戶同步之實施過程

framework hosts dcl eba exec apt pick summary sts

在寫這篇文章的時候,我還在想,這篇文章也許能給你帶來一些收獲,但或許會令你更加的迷茫,為什麽會這樣?
因為:
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 用戶同步之實施過程