其他语言开发UC接口流程说明(附 c#版本的authcode() 函数的代码 )
因为时间关系,我们只推出了PHP版本的UC,在这里我简要给大家说明下其他语言整合UC的流程。
关于UC的工作原理我再简要说明下:
UC相当于一个WEB SERVICE,所有应用(指你的站内的应用)都会来这里登记自己的信息。它起的作用就是一个中心枢纽,可以认为它是一个中转中心,或者是公用数据中心。
在介绍流程时,我将几个关键点说明下:
1. UC 给每个应用分配一个唯一ID,我们称之为 appid。
2. UC 给每个应用分配一个密钥,用来加密/解密数据,防止被窃听,加密函数 authcode()。
3. UC 跟应用通讯的协议为 HTTP,在 PHP 版本的 UC 中,我们实现了非 HTTP 方式,其他语言不用关心这个。
4. 应用发送给 UC 的为 GET/POST 数据,格式与普通表单类似,如 http://server.uc.com/index.php?m=user&a=login
5. UC 回应的数据为 XML 格式,后面我们会详细说明。
6. 本教程以PHP代码为例,供其他语言参考。
7. 假定如下部署:
UC URL: http://uc.dezhifl.com/
应用 URL: http://bbs.dezhifl.com/
接受 UC 通知的地址: http://bbs.dezhifl.com/api/uc.aspx
下面我来说一下具体流程:
第一步:
登录 http://uc.dezhifl.com/ 进入“应用管理” => “添加应用” => 选择自定义安装
通信密钥随便填写几个字符,假定填写的为: abcdefgh。
应用名称: Demo BBS
接口URL : http://bbs.dezhifl.com/
应用IP留空
应用类型: 其他
同步登陆: 是
是否接受通知: 否
标签模板那两条留空。
提交后,提示:成功添加应用。ID:2
第二步:
根据第一个的结果,我们手工编写如下配置文件,保存为 http://bbs.dezhifl.com/uc.config.php
- <?php
- define('UC_API', 'http://bbs.domain.com/'); // UCenter 的 URL 地址
- define('UC_IP', ''); // 避免每次都尝试DNS解析,最好填上
- define('UC_APPID', '2'); // 当前应用的 ID
- define('UC_KEY', 'abcdefgh'); // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
- ?>
复制代码
复制代码
第三步:
发送数据给 UC,比如我们要调用 UC 注册用户的接口。
建立 http://bbs.dezhifl.com/test_uc_reg.php 文件
- <?php
- require '../uc.config.php';
- $username = 'abc';
- $password = '123';
- $email = 'aaa@aaa.com';
- // 构造原始的POST数据
- $postdata = 'username=abc&password=123&email=aaa@aaa.com';
- // 数据加密,加密函数 uc_authcode() ,附件中包含 c# 的实现
- $postdata = urlencode(uc_authcode($postdata.'&agent='.md5($_SERVER['HTTP_USER_AGENT'])."&time=".time(), 'ENCODE', UC_KEY));
- // 指明请求的模块和动作,m=模块 a=动作 inajax=2表示返回的是XML格式 input=表示加密后的数据 appid=应用的ID标示
- // 模块,动作,参数,可以参考 UCenter 1.0.0 接口开发手册
- $postdata = "m=user&a=register&inajax=2&input=$postdata&appid=".UC_APPID;
- // 将数据POST方式发送到 UC $result 为 UC 返回的数据。
- $result = uc_fopen(UC_API.'/index.php', 500000, 'username=abc&password=123&email=aaa@aaa.com', '', TRUE, UC_IP, 20);
- // 返回的结果,可以参考 UCenter 1.0.0 接口开发手册
- if($result == '-1') {
- // 用户名不合法
- } elseif($result == '-2') {
- // 包含不允许注册的词语
- } elseif($result == '-3') {
- // 用户名已经存在
- } elseif($result == '-4') {
- // email 格式有误
- } elseif($result == '-5') {
- // email 不允许注册
- } elseif($result == '-6') {
- // 该 email 已经被注册
- } else {
- // 注册成功, uid 为 $result
- $uid = $result;
- }
- function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE) {
- $return = '';
- $matches = parse_url($url);
- !isset($matches['host']) && $matches['host'] = '';
- !isset($matches['path']) && $matches['path'] = '';
- !isset($matches['query']) && $matches['query'] = '';
- !isset($matches['port']) && $matches['port'] = '';
- $host = $matches['host'];
- $path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
- $port = !empty($matches['port']) ? $matches['port'] : 80;
- if($post) {
- $out = "POST $path HTTP/1.0\r\n";
- $out .= "Accept: */*\r\n";
- //$out .= "Referer: $boardurl\r\n";
- $out .= "Accept-Language: zh-cn\r\n";
- $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
- $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
- $out .= "Host: $host\r\n";
- $out .= 'Content-Length: '.strlen($post)."\r\n";
- $out .= "Connection: Close\r\n";
- $out .= "Cache-Control: no-cache\r\n";
- $out .= "Cookie: $cookie\r\n\r\n";
- $out .= $post;
- } else {
- $out = "GET $path HTTP/1.0\r\n";
- $out .= "Accept: */*\r\n";
- //$out .= "Referer: $boardurl\r\n";
- $out .= "Accept-Language: zh-cn\r\n";
- $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
- $out .= "Host: $host\r\n";
- $out .= "Connection: Close\r\n";
- $out .= "Cookie: $cookie\r\n\r\n";
- }
- $fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
- if(!$fp) {
- return '';//note $errstr : $errno \r\n
- } else {
- stream_set_blocking($fp, $block);
- stream_set_timeout($fp, $timeout);
- @fwrite($fp, $out);
- $status = stream_get_meta_data($fp);
- if(!$status['timed_out']) {
- while (!feof($fp)) {
- if(($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) {
- break;
- }
- }
- $stop = false;
- while(!feof($fp) && !$stop) {
- $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
- $return .= $data;
- if($limit) {
- $limit -= strlen($data);
- $stop = $limit <= 0;
- }
- }
- }
- @fclose($fp);
- return $return;
- }
- }
- /**
- * 字符串加密以及解密函数
- *
- * @param string $string 原文或者密文
- * @param string $operation 操作(ENCODE | DECODE), 默认为 DECODE
- * @param string $key 密钥
- * @param int $expiry 密文有效期, 加密时候有效, 单位 秒,0 为永久有效
- * @return string 处理后的 原文或者 经过 base64_encode 处理后的密文
- *
- * @example
- *
- * $a = authcode('abc', 'ENCODE', 'key');
- * $b = authcode($a, 'DECODE', 'key'); // $b(abc)
- *
- * $a = authcode('abc', 'ENCODE', 'key', 3600);
- * $b = authcode('abc', 'DECODE', 'key'); // 在一个小时内,$b(abc),否则 $b 为空
- */
- function uc_authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
- $ckey_length = 4; //note 随机密钥长度 取值 0-32;
- //note 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
- //note 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
- //note 当此值为 0 时,则不产生随机密钥
- $key = md5($key ? $key : UC_KEY);
- $keya = md5(substr($key, 0, 16));
- $keyb = md5(substr($key, 16, 16));
- $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
- $cryptkey = $keya.md5($keya.$keyc);
- $key_length = strlen($cryptkey);
- $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
- $string_length = strlen($string);
- $result = '';
- $box = range(0, 255);
- $rndkey = array();
- for($i = 0; $i <= 255; $i++) {
- $rndkey[$i] = ord($cryptkey[$i % $key_length]);
- }
- for($j = $i = 0; $i < 256; $i++) {
- $j = ($j + $box[$i] + $rndkey[$i]) % 256;
- $tmp = $box[$i];
- $box[$i] = $box[$j];
- $box[$j] = $tmp;
- }
- for($a = $j = $i = 0; $i < $string_length; $i++) {
- $a = ($a + 1) % 256;
- $j = ($j + $box[$a]) % 256;
- $tmp = $box[$a];
- $box[$a] = $box[$j];
- $box[$j] = $tmp;
- $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
- }
- if($operation == 'DECODE') {
- if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
- return substr($result, 26);
- } else {
- return '';
- }
- } else {
- return $keyc.str_replace('=', '', base64_encode($result));
- }
- }
复制代码
其实整个过程很简单,下个版本我们做了很多改进,在时间允许的情况下,我们会直接推出 .net 版本,敬请期待。
[ 本帖最后由 heyond 于 2008-7-17 11:31 编辑 ] | [attach]37549[/attach]
11.48 KB, 下载次数: 1829
[attach]37550[/attach]
7.77 KB, 下载次数: 2095
|