以下文字摘自网络并加上自己的经验,因为我懒得打太多的字:<
最近公司(假如为www.AAA.com)需要和百度知道(简称bd以下皆同)合作,百度给了开发文档。
好处:省去了我们开发类似的项目,可能还会给网站的访问量有提升。人力物力都省去了,何乐而不为那。
坏处:也谈不上,就是我们的用户提问的问题,给了bd。
既然bd把应用都部署好了,我们还需要开发什么,哈哈,需要的,bd的应用需要使用bd账号登陆,但是我们希望我们的用户
也可以登陆提问问题,所以就有了开发任务。
开发任务: 共4个 。 1.用户登录 2.身份验证 3. 注册 4.退出
目的: 注册为AAA下面的用户,可以在 zhidao.AAA.com (zhidao.AAA.com域名使用cname的方式指向到open.zhidao.baidu.com)中提出问题,回答问题。
因为使用我们自己的二级域名指向了百度,所以,我们百度知道跟我们原来的网站有共同的大域:AAA.com;这样可以实现cookie上共享;
下面我分别解释一下这几个接口干什么用:
一. 用户登录:
1. 回调:callback=http://zhidao.AAA.com/login_finish?token=XXXYYYZZZ 是在我们站点登陆成功后,回调zhidao.AAA.com, 同时把用户名和ID加密传递过去。
就是token的值。 加密时为了安全,传递用户信息是为了在zhidao.AAA.com上面显示用户信息。这时候问题来了,我们传递过去的密文,那怎么显示那?这时候就是身份验证
接口了。
补充:存储cookie的目的: 如果用户在www.AAA.com中直接登陆,这时候是不回调zhidao.AAA.com的。所以bd为了能拿到这个token,需要我们放到cookie里面.
这个我也是猜的。按照道理应该是这样的。
二。身份验证接口:
2.bd 拿到加密的token后,通过get的方式调用身份验证接口,拿到解密的用户信息。显示到页面上。
三. 注册接口
3.如果登陆知道怎么回事了,这个就没有问题了。
四:退出接口:
清除我们存储的cookie;
总结:
说了这么多,其实就是一个get请求。中间把敏感信息进行加密。 还是应了一句老话:万变不离其宗。
这是我开发完成后的理解,如果有不对的地方,欢迎大家指出来,我们共同进步。 如果在开发中也遇到了这样的问题大家多多交流。谢谢!
-------------
我的话:
再跳转到 百度的url +?token=跟cookie一样的值,然后百度还是同样的用这个token到我们的服务器中来验证,成功后,再能进入管理中心,
你也大可不管callback,注册完了,直接回到知道,让用户再点登录才能进去;
退出:
没啥好说的,
清除你自己写的cookie,
直接跳转到callback,意思是告诉百度,我清除了登录状态,你把知道中的页面换成未登录的吧.
ok;
登录的过程是:
点击我们的知道的登录按钮->弹出新的窗口,地址是我们发给百度的登录地址+参数callback=百度url,其实就是给我们的网页传送了一个callback参数,值是百度的地址,这个参数名是固定的,就叫callback,不可以改变->我们的页面处理用户登录成功后,用任何一种方式写入一个cookie值:cookie名(发给百度的那个名字,不能乱用)=xxxyyy(我们自己定的一个串,是为了给后面我们认证用,这个值是什么,就瞧你后面怎么使用),过期时间自己写,访问域最好写AAA.com,接着使用任何方式(js的location,html的跳转,php的header,但这样直接跳就无法显示提示登录成功的信息了)跳转到 百度地址?token=xxxyyy;百度地址就是前面callback的值,参数名token是百度固定的,不能用其它名,它的值 也就是前面保存到cookie中的值;登录完成;=>跳转过去后,百度服务器会直接在服务器边访问我们的认证页面,它使用的方式是get不带cookie或其它的东西,只有一个token=xxxyyy;所以我们的认证就只能基于这个token了;怎么判断呢?那就只能是根据这个token的值来判断前面登录进来的用户是不是注册用户,是就表示可以登录成功了,判断完成后,只要给百度返回一个串如下:
errno=(值有0|-1|-2,0是登录成功,-1是验证失败,-2是不明原因,作用是,登录成功就让进入个人中心,表示你登录了)&uid=(值限数字,最好用库的id,但发现它是有长度限制的,当我使用10位多的数字时,百度白了,作用不明,可能跟百度中的信息相关,最好唯一)&uname=(用户注册名,可以是任何字符,是中文时,必须把此串转成utf8编码,如gbk编码页面提交过来的中文名,否则登录失败,或其它显示用户名不正常的情况发生,它只要是用来在百度个人管理中显示你叫啥,最好唯一)
除了上面的这串,页面中不能再输入其它内容,严格按照此格式,否则一个结果,登录失败;
它在很多时候用到这个验证页面,如进入个人中心时,
百度的验证,理解:首先在client边取得cookie,也就是你提交给百度的那个cookie的参数名中的值,就是token,它存在了,才轮到百度的服务器后台再访问你的验证页面再次确认用户是否登录了;才能进行其它需要权限的操作;
你可以通过触发此验证文件时,把来访问的信息写入一个文件,你就可以看到,当你操作了知道中的什么时,百度服务器会访问你这个验证文件;
注册步骤;
用户点击了注册按钮后,百度直接打开你的提交给百度的那个注册的链接url+?callback=百度的url,
这时你就尽力的去自己弄好用户注册,且记得callback是什么,完成注册后,跟登录一样,写入cookie
dz跟zhidao整合的源文件
1 到dz下载它的应用例子源文件回来,主要有api/client/include文件夹:
code.php/用于加密cookie
<?php
$name_pass_cstr = '123';//用户名和密码分隔字符
$pass_array = array();//密码
may_pass('a','*',$pass_array);// 设置替换密码
function my_encode($in)
{//加密必须从前面换起
global $pass_array;
$in = base64_encode($in);
//echo $in."<BR>";
foreach ($pass_array as $val)
{
$in = str_replace($val[0],$val[1],$in);
}
return $in;
}
function my_decode($in)
{//解密,必须从后面换回
global $pass_array;
for ($for_i = count($pass_array)-1;$for_i >= 0;$for_i--)
{
$in = str_replace($pass_array[$for_i][1],$pass_array[$for_i][0],$in);
}
//echo $in."<BR>";
return base64_decode($in);;
}
function may_pass($old,$new)
{//生成替换密码
//检查规则时注意:加密时是从下标0往后,解密时是从最后下标往前替换,
//base64_encode后,包含字符有:a-z;A-Z;0-9;+/=;四种字符;
//所以,array('旧字符','新字符')设置中注意
//后一个array
//如果[新字符]位置使用非base包含字符,只要前面[新字符]位置未使用过都可以使用;
//如果[新字符]位置使用base包含字符,必须前面某个array[旧字符]位置使用过该字符方可使用;
global $pass_array;
if (!preg_match('/[0-9a-z//=//+///]+/i',$new))
{//非base64包含字符,
$new_i = find_array($new,1);
$old_i = find_array($new,0);
if ((0>$new_i) || ($old_i > $new_i) )
{//前面的新字符中没有使用过就可以使用
//前面的新字符中使用过,必须查找后面此旧字符又被进行过替换,变成不使用过,就可以使用
return $pass_array[count($pass_array)] = array($old,$new);
}else
{
echo "<BR>[非]不能把$old替换成$new<br>";
return 0;
}
}else
{//base64包含字符
$new_i = find_array($new,1);
$old_i = find_array($new);
if ( ($old_i>-1) && ( ($new_i<0) || ($old_i > $new_i) ) )
{//前面旧字符必须使用过+且不在新字符中出现过;或找后面此旧字符又被进行过替换,变成不使用过,就可以使用
return $pass_array[count($pass_array)] = array($old,$new);
}else
{
echo "<BR>[是]不能把$old 替换成 $new<br>";
return 0;
}
}
}
function find_array($find,$index=0)
{//在密码数组中查找,必须指定新/旧字符位置,而且必须往后查起
global $pass_array;
if ( ($index!=0) && ($index!=1)) return -1;
for($for_i = count($pass_array)-1;$for_i >= 0;$for_i--)
{
if ($pass_array[$for_i][$index] == $find) return $for_i;
}
return -2;
}
?>
in.php作用登录
<?php
/**
* UCenter 应用程序开发 知道登录
*/
header('content: text/html; charset=gbk');
if (empty($_GET['callback']) || (!preg_match('/^http//://[^//&]+/i',$_GET['callback'])) ) echo '错误callback参数<BR>';
else
{
$callback = $_GET['callback'];
include './config.inc.php';
include './client/client.php';
include_once ('code.php');
if( isset($_COOKIE['zhidao_user_token']) )
{//登录了
$reback = "$callback?token=".$_COOKIE['zhidao_user_token'];
exit("你已经登录<BR><a href=/"$reback /">5秒后自动返回知道,或者点此立刻返回</a>".
"<script>setTimeout('location=/"$reback /"',5*1000);</script>");//进入知道
} else
{//未登录
if(empty($_POST['submit'])) {
//显示登录表单
?>
<form method="post" action="user_in.php?callback=<?php echo $callback;?>">
登录(<font color=red>测试功能已经打开,运行正常后需要关闭测试功能!</font>):
<dl><dt>用户名</dt><dd><input name="username"></dd>
<dt>密码</dt><dd><input name="password" type="password"></dd></dl>
<input name="submit" type="submit">
</form>
<?php
} else
{
//通过接口判断登录帐号的正确性,返回值为数组
list($uid, $username, $password, $email) = uc_user_login($_POST['username'], $_POST['password']);
if($uid > 0) {
echo uc_user_synlogin($uid);//同步登录
setcookie('zhidao_user_token','', -86400,'/','qidizi.com');//设置知道的登录状态:过期
$token = $uid.$name_pass_cstr.$username.$name_pass_cstr.($password);//密码没有md5过
$token = my_encode($token );//认证串
$cookie_deal = null;//time()+3600000;//过期时间,不设置关闭浏览器删除
setcookie('zhidao_user_token', $token, $cookie_deal ,'/','qidizi.com');//设置知道的登录状态:成功
exit( "登录成功<BR><a href=/"$callback?token=$token/">5秒后自动返回知道,或者点此立刻返回</a>".
"<script>setTimeout('location=/"$callback?token=$token/"',5*1000);</script>");//进入知道
} elseif($uid == -1) echo '用户不存在,或者被删除';
elseif($uid == -2) echo '密码不正确';
else echo '未明错误';
}
}
}
echo '<br><a href="http://zhidao.qidizi.com">返回</a>';
?>
out.php用于退出
<?php
/**
* UCenter 应用程序开发 知道退出操作页面
*/
header('content: text/html; charset=utf-8');
setcookie('zhidao_user_token', '', -89999,'/','qidizi.com');
if (empty($_GET['callback']) || (!preg_match('/^http//://[^//&]+/i',$_GET['callback'])) )
exit('错误callback参数');
header('location:'.$_GET['callback']);//进入知道
?>
reg.php用于注册
<?php
/**
* UCenter 应用程序开发 知道注册
*/
header('content: text/html; charset=gbk');
if (empty($_GET['callback']) || (!preg_match('/^http//://[^//&]+/i',$_GET['callback'])) )
exit('错误callback参数');
$callback = $_GET['callback'];
include './config.inc.php';
include './client/client.php';
/*
* 获取当前用户的 UID 和 用户名
* Cookie 解密直接用 uc_authcode 函数,用户使用自己的函数
*/
if(isset($_COOKIE['zhidao_user_token'])) {
//已登录
header("location: $callback?token=".$_COOKIE['zhidao_user_token']); //进入知道
} else {//未登录
$Example_uid = $Example_username = '';
$reback = 'user_reg.php?callback='.$callback;
if(empty($_POST['submit'])) {
//注册表单
echo '<form method="post" action="'.$reback.'">';
echo '注册:';
echo '<dl><dt>用户名</dt><dd><input name="username"></dd>';
echo '<dt>密码</dt><dd><input name="password"></dd>';
echo '<dt>Email</dt><dd><input name="email"></dd></dl>';
echo '<input name="submit" type="submit">';
echo '</form>';
} else {
//在UCenter注册用户信息
$uid = uc_user_register($_POST['username'], $_POST['password'], $_POST['email']);
if($uid <= 0) {
if($uid == -1) {
echo '用户名不合法';
} elseif($uid == -2) {
echo '包含要允许注册的词语';
} elseif($uid == -3) {
echo '用户名已经存在';
} elseif($uid == -4) {
echo 'Email 格式有误';
} elseif($uid == -5) {
echo 'Email 不允许注册';
} elseif($uid == -6) {
echo '该 Email 已经被注册';
} else {
echo '未定义';
}
echo '<BR><a href="'.$reback.'">返回注册页面</a>';
} else {
//注册成功,设置 Cookie,加密直接用 uc_authcode 函数,用户使用自己的函数
// setcookie('Example_auth', uc_authcode($uid."/t".$_POST['username'], 'ENCODE'));
echo '注册成功<br><a href="'.$callback.'">返回知道</a>';
}
}
}
?>
check文件用于验证
<?php
ob_start();
/**
* UCenter 应用程序开发 知道用户是否登录验证
*/
$name_pass_cstr = ' ';//用户名和密码分隔字符
$uname = '';//用户名
$uid = '';//用户数字标识
$errno = -2;//登录状态代码:验证失败返回errno=-2,验证未登陆返回errno=-1
header('content: text/html; charset=utf-8');
include './config.inc.php';
include './client/client.php';
include_once('code.php');
if (isset($_GET['token']))
{
$name_pass = my_decode($_GET['token']);
$cstr_i = strpos($name_pass,$name_pass_cstr);
//$uid = substr($name_pass,0,$cstr_i);
$name_pass = substr($name_pass,$cstr_i+1);
$cstr_i = strpos($name_pass,$name_pass_cstr);
$uname = substr($name_pass,0,$cstr_i);
$pass = substr($name_pass,$cstr_i+1);
//通过接口判断登录帐号的正确性,返回值为数组
list($uid, $uname, $pass, $email) = uc_user_login($uname, $pass);
if($uid > 0) $errno = 0;//已登录
else $errno = -1;//未登录
}
$re_val = "errno=$errno&uid=$uid&uname=".iconv('gbk','utf-8',$uname);
if (1)
{
//测试代码
echo chr(10).chr(10).chr(10).'清空记录链接:http://bbs.qidizi.com/zhidao_api/re.php'.chr(10);
echo '运行时间 => '.time().chr(10);
echo '返回值(errno=0:登录成功;errno=-2:验证失败;errno=-1:验证未登陆返回) => '.$re_val.chr(10);
echo 'md5($pass)='.md5($pass).chr(10);
echo '_GET = >'.chr(10);var_dump($_GET);
echo '_server = >'.chr(10);var_dump($_SERVER);
$file = 're.txt';
if ($handle=fopen($file,'a'))
{
fwrite($handle,ob_get_contents());
fclose($handle);
}
}
ob_end_clean();
echo $re_val;//返回给知道验证信息
?>
文件链接http://cid-0c051e9a0a1fd5a3.office.live.com/self.aspx/php/zhidao^_api.rar