最近搭建了一个 Discourse 论坛,尝试使用另一个已有的 Django 系统中的账号进行登录。踩了一些小坑,下面记录一下过程。
本文内容基于以下软件以及版本:
Discourse 的安装比较顺利,基本上按官方说明操作即可。最好使用一台没有 Web 服务的机器,即 80 和 443 端口没有被占用,否则会有一些麻烦。
域名我是通过 Cloudflare 管理的,一开始一直遇到“ERR_TOO_MANY_REDIRECTS”错误,查询之后发现是因为“SSL/TLS 加密模式”需要使用“完全”模式,不能使用默认的“灵活”模式。
邮件发送服务,先是试了下阿里云的邮件推送,后来又根据 Discourse 安装说明页面的推荐,选了 Mailjet 的服务。阿里云邮件推送和 Mailjet 都可以支持,且两者每天都有 200 封免费额度,对小应用来说足够了。
Discourse 内置了 Google、Facebook、GitHub、Twitter 等第三方登录,只需在设置中配置开启即可。不过如果想集成自定义 OAuth2 登录服务,还需要安装一个由官方维护的额外插件 discourse-oauth2-basic。
插件安装方式为修改 Discourse 服务器上 /var/discourse/containers
目录下的 app.yml 文件,找到其中 hooks
字段,将插件的 git 仓库地址添加到 cmd
中,如下面的代码所示:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-oauth2-basic.git
注意其中的 docker_manager.git
是默认有的,最后一行的 discourse-oauth2-basic.git
则是新添加的。
添加完成之后,在 /var/discourse
目录下执行以下命令:
./launcher rebuild app
命令的执行过程需要几分钟,完成之后新的配置就生效了。
Django 默认不支持 OAuth2 登录,不过有一个成熟的第三方插件 Django OAuth Toolkit 解决了这个问题,根据官方文档安装即可。
安装完成并在 settings.py
中引入 Django OAuth Toolkit 之后,记得添加下面一项配置:
OAUTH2_PROVIDER = {
# 其他配置项...
'PKCE_REQUIRED': False,
}
Django OAuth Toolkit 默认启用 PCKE,但目前 Discourse 的 OAuth2 插件还不支持 PKCE,如果不把 Django 中的 PKCE_REQUIRED
设为 False
,后面登录时可能会遇到 invalid_request
错误,具体错误描述为“Code challenge required.”。
另外,也需要为 Django OAuth Toolkit 服务指定一个访问地址,比如在站点的 url.py
中添加类似下面的记录:
path('oauth/', include('oauth2_provider.urls', namespace='oauth2_provider')),
之后便可以通过 https://YOUR_DJANGO_SITE/oauth/*
访问 OAuth2 接口。
最后,还需要在 Django 站点中准备一个页面,可以使用 OAuth2 授权访问,页面内容为以 JSON 格式显示的用户信息,以便 Discouse 登录成功后读取用户名、Email 等信息。
在 Django 管理后台的“Django OAuth Toolkit” → “Application”中新添加一条记录。各项填写要点如下:
https://YOUR_DISCOURSE_SITE/auth/oauth2_basic/callback
的值,你需要把中间的 YOUR_DISCOURSE_SITE
替换为你的 Discourse 站点的域名其余没有提到的项使用默认值即可。
最后,再回到 Discourse 这边的配置。
在 Discourse 的插件管理页面,可以看到安装的插件列表,点击 discourse-oauth2-basic
插件的设置按钮可进入对应的设置页面。
当然,你也可以在总设置的“登录”面板下看到相关的设置,不过那个面板选项很多,如果只想设置 OAuth2 相关的选项,可以点击插件的设置按钮以过滤掉无关项。
以下是主要设置项以及说明。
其中 oauth2 authorize url、oauth2 token url 和你的 Django 配置有关,如果你配置的 OAuth2 服务的前缀为 /oauth/
,则对应的地址如下:
# oauth2 authorize url
https://YOUR_DJANGO_SITE/oauth/authorize/
# oauth2 token url
https://YOUR_DJANGO_SITE/oauth/token/
之后的 oauth2 token url method 选择 POST
,再之后的 oauth2 callback user id path 和 oauth2 callback user info paths 留空或使用默认值即可。
再下面则是 oauth2 fetch user details 相关的字段,你需要先在 Django 站点准备好一个页面,比如页面为 https://YOUR_DJANGO_SITE/api/account/info
,返回内容形如:
{
"data": {
"uid": "xxx",
"username": "my_name",
"email": "me@myemail.com"
// ......
}
}
还可以添加更多字段,比如用户全名、头像图片地址、Email 是否已验证等等。
随后,将相关字段填写到接下来的字段中即可。比如:
https://YOUR_DJANGO_SITE/api/account/info
data.uid
data.username
data.email
其余字段根据需要填写即可。
如果一切顺利,你的 Discourse 站点就可以使用 Django 站点的账号登录了。