flaskbb 配置与 AD 登录
今天花了3个小时把公司内网论坛架好了,同时接入了公司的 Active Directory 服务器账号登录。在此做一点记录。
因为最近用 flask 写了几个网站,所以论坛系统我也选择了 flaskbb,方便平时改着玩儿。它是一个基于 flask 的轻量级论坛,在 Github 上有 800+ follows,它使用了大量的 flask 插件来简化开发,自身也支持插件系统。
依赖
应该使用 python 2.7 来部署 flaskbb。
为了支持 MySQL,我们需要安装一个数据库驱动库,这里我选择 PyMySQL,它使用纯 Python 实现,在 Python2/3 下都可以使用。使用 pip install pymysql
安装它。
为了支持 LDAP 协议,我们需要安装一个 LDAP 驱动。这里我选择 ldap3,我在 实现 LDAP 验证登录 中做过介绍。它也是使用纯 Python 实现, 同时兼容 Python2/3 。使用 pip install ldap3
安装它。
基于 MySQL 安装
默认配置文件中使用的数据库系统是 sqlite。如果要使用 MySQL,需要做一些小小的修改。
首先,需要修改官方配置文件中的 SQLALCHEMY_DATABASE_URI
为如下所示:
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://zrong:password@localhost/flaskbb'
这里的配置已经指定使用 MySQL 数据库,而且采用 pymysql 作为数据库驱动,数据库名称是 flaskbb。flaskbb 应该是一个已经存在的数据库,而且内容为空。除了基本的 SELECT/INSERT/UPDATE/DELETE 权限外,zrong 这个帐号需要有 ALTER/CREATE/INDEX 权限。
接下来,需要初始化数据库。如果按照官方文档所说执行 make install
多半是不成功的,会提示表不存在。这可能是由于作者没有仔细测试,或者没有更新文档的原因。正确的用法应该是执行下面的命令对数据库进行初始化(建表,填充必要数据):
1python manage.py initdb
然后创建一个管理员,命令行会询问帐号和密码等信息:
1python manage.py create_admin
如果要显示中文翻译(并不完全),还可以编译语言文件:
1python manage.py compile_translations
BTW: flaskbb 采用的是 GNU gettext 实现多语言支持的,这和 Wordpress 一样。我曾经写过一个 lua 封装:在Lua中使用gettext实现多语言支持。在 Python 中,babel 就带有 gettext 的支持。
LDAP (AD) 集成
我在 实现 LDAP 验证登录 中已经介绍过 Python 的 LDAP 实现。这里介绍一下应该如何修改 flaskbb 使其支持与公司的 AD 服务器集成。
一开始我准备采用 flaskbb 的 插件系统 来实现这个功能,这样就可以不必修改源码。但我仔细看了官方提供的 Portal 插件的实现后后发现,flaskbb 中的插件机制是通过预埋 event 钩子来实现注入的。这个 event 必须自己埋入代码中才能生效。这就违背了我不愿意改源码的初衷。时间有限,插件的机制后面再深究,先把功能实现再说。
LDAP 服务器的信息需要加入到配置项中,我修改了 configs/production.py.example ,这些项目必须配置才能实现 LDAP 登录:
1# LDAP Settings
2# ------------------------------ #
3# For LDAP authorize
4LDAP_SERVER = 'ldapserver.example.org'
5LDAP_PORT = None
6LDAP_USER_FMT = 'Yourcompany\\%s'
7LDAP_EMAIL_SUFFIX = '@example.org'
我增加了一个 staticmethod User._check_login_password
,在这个方法中提供用户名和密码,读取上述配置,去指定的 LDAP 服务器鉴权。
帐号鉴权调用的是 user/models.py
中的 User.authenticate
方法。这是个 classmethod 。我增加了一个 User.authenticate_ldap
classmethod 用来替换原始方法,这个修改的方法中会调用 User._check_login_password
。
这个方法的实现流程为:先检测帐号的合法性,去 AD 服务器鉴权。若鉴权成功,就查询 flashbb 的数据库中有没有该账号,若有则更新登录时间,若无则在 flaskbb 的 users 表中创建该帐号,将密码置为 'password' ,并立即启用该帐号。
1user = User(username=login,
2 email=login+email_suffix,
3 password='password',
4 date_joined=time_utcnow(),
5 primary_group_id=4,
6 language='zh',
7 activated=True)
8user.save()
由于鉴权完全使用 AD 服务器实现,在 users 表中 不应该 保存密码。
完整的方法可查看 User.authenticate_ldap
。
调用鉴权的位置是 auth/views.py
中的 login
路由。将这个路由的端点注释掉,改名为 login_origin
,创建一个新的 login
方法,使其调用 User.authenticate_ldap
方法进行鉴权。
完整的方法可查看 login
。
2016-11-17 增加:
在 auth/views.py
中还有一个 reauth
方法需要重新实现。reauth
用来重新验证用户的密码。我们需要取得用户的账号,带上用户输入的密码去 LDAP 服务器进行鉴权。修改后的 reauth 方法直接调用 User.check_password_ldap
来进行鉴权。
完整的方法可查看 reauth
。
禁用功能
由于鉴权完全使用 AD 服务器实现,注册账号、修改账号、重置密码、修改密码、修改 email 等功能都需要禁用。
注册账号的功能可以直接在 flaskbb 的后台中取消。其他几个功能则需要修改源码实现。
忘记密码和重置密码功能在 auth/views.py
的 forgot_password
和 reset_password
中,abort(403)
即可:
1@auth.route('/reset-password', methods=["GET", "POST"])
2def forgot_password():
3 """Sends a reset password token to the user."""
4 # zrong start 2016-11-16 No permission to reset password when login by LDAP
5 abort(403)
6 # zrong end 2016-11-16
完整的方法可查看 forgot_password
和 reset_password
。
修改密码和修改 email 功能在 user/views.py
的 change_password
和 change_email
中,处理方法相同。
1@user.route("/settings/password", methods=["POST", "GET"])
2@login_required
3def change_password():
4 # zrong start 2016-11-16 No permission to modify password when login by LDAP
5 abort(403)
6 # zrong end 2016-11-16
完整的方法可查看 change_password
和 change_email
。
最后的部署,当然是看我之前写的 部署Flask + uWSGI + Nginx 啦!全部搞定!
(全文完)
- 文章ID:2605
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/flashbb-and-ad/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。