开篇首先感谢下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' ]; |
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 )); |
09 | return $url . "/api/$apifilename?code=$code" ; |
因为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) |
03 | throw new NotImplementedException(); |
06 | public override ApiReturn RenameUser( int uid, string oldUserName, string newUserName) |
08 | throw new NotImplementedException(); |
11 | public override UcTagReturns GetTag( string tagName) |
13 | throw new NotImplementedException(); |
16 | public override ApiReturn SynLogin( int uid) |
18 | throw new NotImplementedException(); |
21 | public override ApiReturn SynLogout() |
23 | throw new NotImplementedException(); |
26 | public override ApiReturn UpdatePw( string userName, string passWord) |
28 | throw new NotImplementedException(); |
31 | public override ApiReturn UpdateBadWords(UcBadWords badWords) |
33 | throw new NotImplementedException(); |
36 | public override ApiReturn UpdateHosts(UcHosts hosts) |
38 | throw new NotImplementedException(); |
41 | public override ApiReturn UpdateApps(UcApps apps) |
43 | throw new NotImplementedException(); |
46 | public override ApiReturn UpdateClient(UcClientSetting client) |
48 | throw new NotImplementedException(); |
51 | public override ApiReturn UpdateCredit( int uid, int credit, int amount) |
53 | throw new NotImplementedException(); |
56 | public override UcCreditSettingReturns GetCreditSettings() |
58 | throw new NotImplementedException(); |
61 | public override ApiReturn GetCredit( int uid, int credit) |
63 | throw new NotImplementedException(); |
66 | public override ApiReturn UpdateCreditSettings(UcCreditSettings creditSettings) |
68 | throw new NotImplementedException(); |
其中SynLogin,SynLogout俩个函数就是实现同步登出登录的。
注:如果需要实现写入Session等操作,那不妨像我一样修改下SDK代码,接下来的修改很重要
修改SDK中的UcApiBase文件中的如下方法:
001 | public void ProcessRequest(HttpContext context) |
003 | Response = context.Response; |
004 | Request = context.Request; |
005 | Args = new UcRequestArguments(Request); |
006 | if (!check()) return ; |
007 | switchAction(context); |
011 | private HttpResponse Response { get ; set ; } |
012 | private HttpRequest Request { get ; set ; } |
013 | private IUcRequestArguments Args { get ; set ; } |
017 | /// <returns></returns> |
020 | if (Args.IsInvalidRequest) |
022 | writeEnd( "Invalid Request" ); |
024 | if (Args.IsAuthracationExpiried) |
026 | writeEnd( "Authracation has expiried" ); |
030 | private void writeEnd( string msg) |
035 | private void writeEnd<T>(UcCollectionReturnBase<T> msg) |
036 | where T : UcItemReturnBase |
038 | writeEnd(msg.ToString()); |
040 | private void writeEnd(ApiReturn result) |
042 | var msg = result == ApiReturn.Success ? UcConfig.ApiReturnSucceed : UcConfig.ApiReturnFailed; |
046 | private void writeForbidden() |
048 | writeEnd(UcConfig.ApiReturnForbidden); |
050 | private void switchAction(HttpContext context) |
052 | if (Args.Action == UcActions.Test) |
056 | else if (Args.Action == UcActions.DeleteUser) |
060 | else if (Args.Action == UcActions.RenameUser) |
064 | else if (Args.Action == UcActions.GetTag) |
068 | else if (Args.Action == UcActions.SynLogin) |
072 | else if (Args.Action == UcActions.SynLogout) |
076 | else if (Args.Action == UcActions.UpdatePw) |
080 | else if (Args.Action == UcActions.UpdateBadWords) |
084 | else if (Args.Action == UcActions.UpdateHosts) |
088 | else if (Args.Action == UcActions.UpdateApps) |
092 | else if (Args.Action == UcActions.UpdateClient) |
096 | else if (Args.Action == UcActions.UpdateCredit) |
100 | else if (Args.Action == UcActions.GetCreditSettings) |
104 | else if (Args.Action == UcActions.GetCredit) |
108 | else if (Args.Action == UcActions.UpdateCreditSettings) |
110 | updateCreditSettings(); |
将请求上下文传入到方法中,这样我们就可以在uc.ashx写Session了,将SynLogin,SynLogout修改成:
01 | public override ApiReturn SynLogin( int uid, HttpContext context) |
05 | IUcClient client = new UcClient(); |
06 | UcUserInfo user = client.UserInfo(uid); |
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; |
15 | return ApiReturn.Failed; |
19 | LoggerCore.Debug( "远程登录错误" , ex); |
20 | return ApiReturn.Failed; |
24 | public override ApiReturn SynLogout(HttpContext context) |
28 | context.Session.Abandon(); |
36 | return ApiReturn.Success; |
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同步登陆登出,配置如下:
03 | < add key = "UC_CLIENT_VERSION" value = "1.5.2" /> |
05 | < add key = "UC_CLIENT_RELEASE" value = "20101001" /> |
09 | < add key = "API_DELETEUSER" value = "True" /> |
11 | < add key = "API_RENAMEUSER" value = "True" /> |
13 | < add key = "API_GETTAG" value = "True" /> |
15 | < add key = "API_SYNLOGIN" value = "True" /> |
17 | < add key = "API_SYNLOGOUT" value = "True" /> |
19 | < add key = "API_UPDATEPW" value = "True" /> |
21 | < add key = "API_UPDATEBADWORDS" value = "True" /> |
23 | < add key = "API_UPDATEHOSTS" value = "True" /> |
25 | < add key = "API_UPDATEAPPS" value = "True" /> |
27 | < add key = "API_UPDATECLIENT" value = "True" /> |
29 | < add key = "API_UPDATECREDIT" value = "True" /> |
31 | < add key = "API_GETCREDITSETTINGS" value = "True" /> |
33 | < add key = "API_GETCREDIT" value = "True" /> |
35 | < add key = "API_UPDATECREDITSETTINGS" value = "True" /> |
40 | < add key = "API_RETURN_SUCCEED" value = "1" /> |
42 | < add key = "API_RETURN_FAILED" value = "-1" /> |
44 | < add key = "API_RETURN_FORBIDDEN" value = "-2" /> |
48 | < add key = "UC_KEY" value = "xxxxxxxxx" /> |
52 | < add key = "UC_CHARSET" value = "utf-8" /> |
54 | < add key = "UC_IP" value = "" /> |
56 | < add key = "UC_APPID" value = "2" /> |
四、发布网站后修改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官方主页