标签:
开篇首先感谢下Dozer同学,他的几篇博文帮助CoderMan省下了很多工作,通过反编译官方的DLLDozer同学二次开发的SDK,我也是丝毫不客气的就拿来直接用了。
那我们就来一步步说一下Asp.net通过Ucenter与Discuz X系列的整合了。
首先搭建自己的网站,在网站目录下建立API文件夹(必须是API文件夹),开始我很疑惑,后来通过查看Discuz的源代码发现了原因,打开uc_server\model\note.php文件找到get_url_code方法,这个方法是每次接口获取远程地址的方法,仔细观察下代码就知道为什么接收页地址父文件夹一定要叫API了:
01 |
function get_url_code( $operation , $getdata , $appid )
{ |
02 |
$app = $this ->apps[ $appid ]; |
03 |
$authkey = $app [ ‘authkey‘ ]; |
04 |
$url = $app [ ‘url‘ ]; |
05 |
$apifilename =
isset( $app [ ‘apifilename‘ ])
&& $app [ ‘apifilename‘ ]
? $app [ ‘apifilename‘ ]
: ‘uc.php‘ ; |
06 |
$action = $this ->operations[ $operation ][1]; |
07 |
$code =
urlencode( $this ->base->authcode( "$action&" .( $getdata ? "$getdata&" : ‘‘ ). "time=" . $this ->base->time, ‘ENCODE‘ , $authkey )); |
08 |
|
09 |
return $url . "/api/$apifilename?code=$code" ; |
10 |
} |
因为Discuz的源代码里面竟然在接收页地址路径前加了API,Coderman认为这样不好,害得很多人调试半天通不了。说了废话一堆,看不下去的朋友肯定自己调试的时候要吃亏了。下面开始步入正题:一、引入SDK,建立接收页
SDK下载地址:https://github.com/dozer47528/UCenter-API-For-DotNet
接下来建立uc.ashx文件如下:
继承SDK中的接口UcApiBase,有如下方法重载:
01 |
public override ApiReturn
DeleteUser(IEnumerable< int >
ids) |
02 |
{ |
03 |
throw new NotImplementedException(); |
04 |
} |
05 |
06 |
public override ApiReturn
RenameUser( int uid, string oldUserName, string newUserName) |
07 |
{ |
08 |
throw new NotImplementedException(); |
09 |
} |
10 |
11 |
public override UcTagReturns
GetTag( string tagName) |
12 |
{ |
13 |
throw new NotImplementedException(); |
14 |
} |
15 |
16 |
public override ApiReturn
SynLogin( int uid) |
17 |
{ |
18 |
throw new NotImplementedException(); |
19 |
} |
20 |
21 |
public override ApiReturn
SynLogout() |
22 |
{ |
23 |
throw new NotImplementedException(); |
24 |
} |
25 |
26 |
public override ApiReturn
UpdatePw( string userName, string passWord) |
27 |
{ |
28 |
throw new NotImplementedException(); |
29 |
} |
30 |
31 |
public override ApiReturn
UpdateBadWords(UcBadWords badWords) |
32 |
{ |
33 |
throw new NotImplementedException(); |
34 |
} |
35 |
36 |
public override ApiReturn
UpdateHosts(UcHosts hosts) |
37 |
{ |
38 |
throw new NotImplementedException(); |
39 |
} |
40 |
41 |
public override ApiReturn
UpdateApps(UcApps apps) |
42 |
{ |
43 |
throw new NotImplementedException(); |
44 |
} |
45 |
46 |
public override ApiReturn
UpdateClient(UcClientSetting client) |
47 |
{ |
48 |
throw new NotImplementedException(); |
49 |
} |
50 |
51 |
public override ApiReturn
UpdateCredit( int uid, int credit, int amount) |
52 |
{ |
53 |
throw new NotImplementedException(); |
54 |
} |
55 |
56 |
public override UcCreditSettingReturns
GetCreditSettings() |
57 |
{ |
58 |
throw new NotImplementedException(); |
59 |
} |
60 |
61 |
public override ApiReturn
GetCredit( int uid, int credit) |
62 |
{ |
63 |
throw new NotImplementedException(); |
64 |
} |
65 |
66 |
public override ApiReturn
UpdateCreditSettings(UcCreditSettings creditSettings) |
67 |
{ |
68 |
throw new NotImplementedException(); |
69 |
} |
其中SynLogin,SynLogout俩个函数就是实现同步登出登录的。
注:如果需要实现写入Session等操作,那不妨像我一样修改下SDK代码,接下来的修改很重要
修改SDK中的UcApiBase文件中的如下方法:
001 |
public void ProcessRequest(HttpContext
context) |
002 |
{ |
003 |
Response
= context.Response; |
004 |
Request
= context.Request; |
005 |
Args
= new UcRequestArguments(Request); |
006 |
if (!check()) return ; |
007 |
switchAction(context); |
008 |
} |
009 |
010 |
#region
私有 |
011 |
private HttpResponse
Response { get ; set ;
} |
012 |
private HttpRequest
Request { get ; set ;
} |
013 |
private IUcRequestArguments
Args { get ; set ;
} |
014 |
///
<summary> |
015 |
///
检查合法性 |
016 |
///
</summary> |
017 |
///
<returns></returns> |
018 |
private bool check() |
019 |
{ |
020 |
if (Args.IsInvalidRequest) |
021 |
{ |
022 |
writeEnd( "Invalid
Request" ); |
023 |
} |
024 |
if (Args.IsAuthracationExpiried) |
025 |
{ |
026 |
writeEnd( "Authracation
has expiried" ); |
027 |
} |
028 |
return true ; |
029 |
} |
030 |
private void writeEnd( string msg) |
031 |
{ |
032 |
Response.Write(msg); |
033 |
Response.End(); |
034 |
} |
035 |
private void writeEnd<T>(UcCollectionReturnBase<T>
msg) |
036 |
where
T : UcItemReturnBase |
037 |
{ |
038 |
writeEnd(msg.ToString()); |
039 |
} |
040 |
private void writeEnd(ApiReturn
result) |
041 |
{ |
042 |
var
msg = result == ApiReturn.Success ? UcConfig.ApiReturnSucceed : UcConfig.ApiReturnFailed; |
043 |
Response.Write(msg); |
044 |
Response.End(); |
045 |
} |
046 |
private void writeForbidden() |
047 |
{ |
048 |
writeEnd(UcConfig.ApiReturnForbidden); |
049 |
} |
050 |
private void switchAction(HttpContext
context) |
051 |
{ |
052 |
if (Args.Action
== UcActions.Test) |
053 |
{ |
054 |
test(); |
055 |
} |
056 |
else if (Args.Action
== UcActions.DeleteUser) |
057 |
{ |
058 |
deleteUser(); |
059 |
} |
060 |
else if (Args.Action
== UcActions.RenameUser) |
061 |
{ |
062 |
renameUser(); |
063 |
} |
064 |
else if (Args.Action
== UcActions.GetTag) |
065 |
{ |
066 |
getTag(); |
067 |
} |
068 |
else if (Args.Action
== UcActions.SynLogin) |
069 |
{ |
070 |
synLogin(context); |
071 |
} |
072 |
else if (Args.Action
== UcActions.SynLogout) |
073 |
{ |
074 |
synLogout(context); |
075 |
} |
076 |
else if (Args.Action
== UcActions.UpdatePw) |
077 |
{ |
078 |
updatePw(); |
079 |
} |
080 |
else if (Args.Action
== UcActions.UpdateBadWords) |
081 |
{ |
082 |
updateBadWords(); |
083 |
} |
084 |
else if (Args.Action
== UcActions.UpdateHosts) |
085 |
{ |
086 |
updateHosts(); |
087 |
} |
088 |
else if (Args.Action
== UcActions.UpdateApps) |
089 |
{ |
090 |
updateApps(); |
091 |
} |
092 |
else if (Args.Action
== UcActions.UpdateClient) |
093 |
{ |
094 |
updateClient(); |
095 |
} |
096 |
else if (Args.Action
== UcActions.UpdateCredit) |
097 |
{ |
098 |
updateCredit(); |
099 |
} |
100 |
else if (Args.Action
== UcActions.GetCreditSettings) |
101 |
{ |
102 |
getCreditSettings(); |
103 |
} |
104 |
else if (Args.Action
== UcActions.GetCredit) |
105 |
{ |
106 |
getCredit(); |
107 |
} |
108 |
else if (Args.Action
== UcActions.UpdateCreditSettings) |
109 |
{ |
110 |
updateCreditSettings(); |
111 |
} |
112 |
} |
将请求上下文传入到方法中,这样我们就可以在uc.ashx写Session了,将SynLogin,SynLogout修改成:
01 |
public override ApiReturn
SynLogin( int uid,
HttpContext context) |
02 |
{ |
03 |
try |
04 |
{ |
05 |
IUcClient
client = new UcClient(); |
06 |
UcUserInfo
user = client.UserInfo(uid); |
07 |
if (user.Success) |
08 |
{ |
09 |
LoggerCore.Debug(user.Uid
+ "--" +
user.UserName); |
10 |
context.Session[ "uid" ]
= user.Uid; |
11 |
context.Session[ "username" ]
= user.UserName; |
12 |
context.Session[ "email" ]
= user.Mail; |
13 |
return ApiReturn.Success; |
14 |
} |
15 |
return ApiReturn.Failed; |
16 |
} |
17 |
catch (Exception
ex) |
18 |
{ |
19 |
LoggerCore.Debug( "远程登录错误" ,
ex); |
20 |
return ApiReturn.Failed; |
21 |
} |
22 |
} |
23 |
24 |
public override ApiReturn
SynLogout(HttpContext context) |
25 |
{ |
26 |
try |
27 |
{ |
28 |
context.Session.Abandon(); |
29 |
} |
30 |
catch (Exception) |
31 |
{ |
32 |
|
33 |
throw ; |
34 |
} |
35 |
|
36 |
return ApiReturn.Success; |
37 |
} |
C#部分的代码修改到这里就结束了。
二、配置Ucenter
如下图: 通信密钥的地方大家随便填,生成一段Guid也是可以的。 运行你的Asp.net项目,是不是通信成功了?
Coderman走到这一步蛋蛋差点碎了,因为调试半天都特么的不成功,百思不得其解,查看数据库,调试Discuz的源码,最后发现原来通信配置是通过生成的配置文件缓存读取的,好吧,速度赶紧把Cache删除掉吧,注意有俩处,一处是uc_server文件下的uc_server\data\cache\apps.php,这负责的是Ucenter与第三方应用之间的通信;另外一处是uc_client\data\cache\apps.php,这负责Discuz登录或者其它用户操作通知第三方应用。 至此,通信应该成功了,运行Asp.net代码,在SynLogin方法处打上断点,去Discuz网站前台登录吧,本地LocalHost应该是通信成功了。
三、修改Asp.net的Web.config文件
用于Asp.net程序通知Discuz同步登陆登出,配置如下:
01 |
< appSettings > |
02 |
<!--客户端版本--> |
03 |
< add key = "UC_CLIENT_VERSION" value = "1.5.2" /> |
04 |
<!--发行时间--> |
05 |
< add key = "UC_CLIENT_RELEASE" value = "20101001" /> |
06 |
07 |
<!--API
开关(value类型:True False 默认值:True)--> |
08 |
<!--是否允许删除用户--> |
09 |
< add key = "API_DELETEUSER" value = "True" /> |
10 |
<!--是否允许重命名用户--> |
11 |
< add key = "API_RENAMEUSER" value = "True" /> |
12 |
<!--是否允许得到标签--> |
13 |
< add key = "API_GETTAG" value = "True" /> |
14 |
<!--是否允许同步登录--> |
15 |
< add key = "API_SYNLOGIN" value = "True" /> |
16 |
<!--是否允许同步登出--> |
17 |
< add key = "API_SYNLOGOUT" value = "True" /> |
18 |
<!--是否允许更改密码--> |
19 |
< add key = "API_UPDATEPW" value = "True" /> |
20 |
<!--是否允许更新关键字--> |
21 |
< add key = "API_UPDATEBADWORDS" value = "True" /> |
22 |
<!--是否允许更新域名解析缓存--> |
23 |
< add key = "API_UPDATEHOSTS" value = "True" /> |
24 |
<!--是否允许更新应用列表--> |
25 |
< add key = "API_UPDATEAPPS" value = "True" /> |
26 |
<!--是否允许更新客户端缓存--> |
27 |
< add key = "API_UPDATECLIENT" value = "True" /> |
28 |
<!--是否允许更新用户积分--> |
29 |
< add key = "API_UPDATECREDIT" value = "True" /> |
30 |
<!--是否允许向UCenter提供积分设置--> |
31 |
< add key = "API_GETCREDITSETTINGS" value = "True" /> |
32 |
<!--是否允许获取用户的某项积分--> |
33 |
< add key = "API_GETCREDIT" value = "True" /> |
34 |
<!--是否允许更新应用积分设置--> |
35 |
< add key = "API_UPDATECREDITSETTINGS" value = "True" /> |
36 |
<!--API
开关结束--> |
37 |
38 |
<!--返回值设置--> |
39 |
<!--返回成功(默认:1)--> |
40 |
< add key = "API_RETURN_SUCCEED" value = "1" /> |
41 |
<!--返回失败(默认:-1)--> |
42 |
< add key = "API_RETURN_FAILED" value = "-1" /> |
43 |
<!--返回禁用(默认:-2)--> |
44 |
< add key = "API_RETURN_FORBIDDEN" value = "-2" /> |
45 |
<!--返回值设置结束--> |
46 |
47 |
<!--[必填]通信密钥--> |
48 |
< add key = "UC_KEY" value = "xxxxxxxxx" /> |
49 |
<!--[必填]UCenter地址--> |
50 |
< add key = "UC_API" value = "http://www.xxxxxx.com/uc_server" /> |
51 |
<!--[必填]默认编码--> |
52 |
< add key = "UC_CHARSET" value = "utf-8" /> |
53 |
<!--[非必填]UCenter
IP--> |
54 |
< add key = "UC_IP" value = "" /> |
55 |
<!--[必填]应用ID--> |
56 |
< add key = "UC_APPID" value = "2" /> |
57 |
</ appSettings > |
四、发布网站后修改Cookie域
本地好好的同步登录登出放到服务器上确不太灵光了,想了想是不是Cookie域的原因。首先修改Discuz的Cookie域,找到配置文件,修改配置文件:
1 |
$_config [ ‘cookie‘ ][ ‘cookiepre‘ ]
= ‘hUDo_‘ ; |
2 |
$_config [ ‘cookie‘ ][ ‘cookiedomain‘ ]
= ‘.cartrip.cc‘ ; |
3 |
$_config [ ‘cookie‘ ][ ‘cookiepath‘ ]
= ‘/‘ ; |
再来到Asp.net的Web.config添加或者修改cookie域:
1 |
< httpCookies domain = ".cartrip.cc" /> |
结束语:再次感谢Dozer的无私奉献,帮大家节省了很多时间和精力,Coderman的俩个网站也已经这样一步步实现了同步登陆和登出,分别是http://www.cartrip.cc和http://piao.cartrip.cc。有朋友认真看完了的话还没有成功的话,那可能是Coderman写的还是不够清楚,那就联系我批斗我吧。
注:文章由CoderMan原创,转载请说明出处:CoderMan官方主页
Asp.net整合Disucuz X 通过Ucenter同步登陆
标签:
原文地址:http://blog.csdn.net/taolinsen/article/details/43226257