MoinMoin Wiki是Python开发的, Discuz论坛由PHP开发带有Passport整合接口, 综合考虑将Wiki做为主登陆界面, 采用Url传递认证方式同步论坛用户是最简单的方案. 由于在使用论坛Passport登陆过程中客户端无法创建cookie的问题始终没有解决, 因此只同步2个系统中的账户, 登陆仍然需要分别在2个系统中登陆, 虽然不完美, 但不影响实际使用, 2个系统都有cookie, 只需分别一次登陆即可.
实现:
- 关闭论坛注册, 所有用户只能从Wiki注册.
- 刚注册的用户首先需要在Wiki登陆, 通过Wiki认证后调用Url至论坛Passport同步建立论坛账户.
- 用户修改密码时需要在Wiki修改, 然后重复第二项.
代码修改:
修改MoinMoin Wiki中\Lib\site-packages\MoinMoin\action\login.py, Wiki账户密码采用了不可逆加密方式, 因此只有在这里才能获取到用户原始密码. 通过Wiki认证后, 将账户参数组成为论坛Passport格式Url再传递给论坛. 以下代码对称加密过程请自己完成.
1
if
request.user.valid:
2
account
=
user.User(request, user.getUserId(request, name))
3
import
urllib, time, base64, md5
4
#
认证key, 自定义
5
mykey
=
'
1111111
'
6
#
选择md5加密方式和论坛加密方式统一
7
password
=
md5.new(password).hexdigest()
8
email
=
account.email
9
#
系统时间戳, 防止过期url伪装
10
mytime
=
time.time()
11
12
auth
=
{
'
time
'
:mytime,
'
username
'
:name,
'
password
'
:password,
'
email
'
:email}
13
#
为了处理中文用户名需要加入utf8编码, 安全起见这里需要使用自己的对称加密方式加密此字符串
14
auth
=
(
'
&
'
.join([
"
%s=%s
"
%
(k, v)
for
k, v
in
auth.items()])).encode(
'
utf8
'
)
15
#
url的验证字符串
16
verify
=
md5.new(auth
+
mykey).hexdigest()
17
args
=
urllib.urlencode({
'
auth
'
:auth,
'
verify
'
:verify})
18
#
生成论坛passport url
19
myurl
=
'
http://bbs.cwowaddon.com/api/passport.php?action=login&
'
+
args
20
21
request.http_redirect(myurl)
22
return
request.finish()
在论坛方面因登陆无法创建cookie的问题, 既需要使用passport功能又不希望它完全开启, 因为完全开启会改变论坛的注册, 登陆, 注销的Url. 因此需要动些手脚, 打开数据库xxx_settings表, 找到passport_xxx这样的字段并修改:
passport_expire
3600
passport_extcredits
0
passport_key
1111111
passport_login_url passport_logout_url passport_register_url passport_status passport_url http://wiki.cwowaddon.com/
然后需要修改api\passport.php
1
if
(
$_DCACHE
[
'
settings
'
][
'
passport_status
'
]
!=
'
passport
'
) {
2
exit
(
'
Passport disabled
'
);
3
}
elseif
(
$_GET
[
'
verify
'
]
!=
md5
(
$_GET
[
'
action
'
]
.
$_GET
[
'
auth
'
]
.
$_GET
[
'
forward
'
]
.
$_DCACHE
[
'
settings
'
][
'
passport_key
'
])) {
4
exit
(
'
Illegal request
'
);
5
}
将上面的代码替换为下面的部分, 以开启passport.
1
if
(
$_GET
[
'
verify
'
]
!=
md5
(
$_GET
[
'
auth
'
]
.
$_GET
[
'
forward
'
]
.
$_DCACHE
[
'
settings
'
][
'
passport_key
'
])) {
2
exit
(
'
Illegal request
'
);
3
}
下面的加密方法需要你自己完成, 保证和wiki中的加密解密方法一样.
1
function
passport_encrypt(
$txt
,
$key
) {
2
//
....
3
}
4
5
function
passport_decrypt(
$txt
,
$key
) {
6
//
....
7
}
8
9
function
passport_key(
$txt
,
$encrypt_key
) {
10
$encrypt_key
=
md5
(
$encrypt_key
);
11
$ctr
=
0
;
12
$tmp
=
''
;
13
for
(
$i
=
0
;
$i
<
strlen
(
$txt
);
$i
++
) {
14
$ctr
=
$ctr
==
strlen
(
$encrypt_key
)
?
0
:
$ctr
;
15
$tmp
.=
$txt
[
$i
]
^
$encrypt_key
[
$ctr
++
];
16
}
17
return
$tmp
;
18
}
关于Passsport请参见Discuz论坛文档有很详细的说明.