Discourse 集成 Django 登录
最近搭建了一个 Discourse 论坛,尝试使用另一个已有的 Django 系统中的账号进行登录。踩了一些小坑,下面记录一下过程。
本文内容基于以下软件以及版本:
- Discourse 3.1.0.beta5
- Django 4.2.2
- Django Oauth Toolkit 2.3.0
安装 Discourse
Discourse 的安装比较顺利,基本上按官方说明操作即可。最好使用一台没有 Web 服务的机器,即 80 和 443 端口没有被占用,否则会有一些麻烦。
域名我是通过 Cloudflare 管理的,一开始一直遇到“ERR_TOO_MANY_REDIRECTS”错误,查询之后发现是因为“SSL/TLS 加密模式”需要使用“完全”模式,不能使用默认的“灵活”模式。
邮件发送服务,先是试了下阿里云的邮件推送,后来又根据 Discourse 安装说明页面的推荐,选了 Mailjet 的服务。阿里云邮件推送和 Mailjet 都可以支持,且两者每天都有 200 封免费额度,对小应用来说足够了。
Discourse 准备
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 准备
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 管理后台的“Django OAuth Toolkit” → “Application”中新添加一条记录。各项填写要点如下:
- Client id:使用默认值或你指定的值
- User:留空
- Redirect uris:填写形如
https://YOUR_DISCOURSE_SITE/auth/oauth2_basic/callback
的值,你需要把中间的YOUR_DISCOURSE_SITE
替换为你的 Discourse 站点的域名 - Client type:选择“Confidential”
- Authorization grant type:选择“Authorization code”
- Client secret:使用默认值或你指定的值,注意如果你决定使用默认值,需要在第一次添加记录时将值复制出来,因为后面再打开这条记录时将只能看到哈希后的值
- Name:取一个容易记忆或识别的名字即可,比如“Discourse”
- Skip authorization:此项用于控制在登录成功之后,要不要给用户显示一个是否授权登录的确认页面。建议勾选,因为那个页面默认样式很简陋,影响体验
其余没有提到的项使用默认值即可。
Discourse 配置
最后,再回到 Discourse 这边的配置。
在 Discourse 的插件管理页面,可以看到安装的插件列表,点击 discourse-oauth2-basic
插件的设置按钮可进入对应的设置页面。
当然,你也可以在总设置的“登录”面板下看到相关的设置,不过那个面板选项很多,如果只想设置 OAuth2 相关的选项,可以点击插件的设置按钮以过滤掉无关项。
以下是主要设置项以及说明。
- oauth2 enabled:选中此项以启用 OAuth2 登录
- oauth2 client id:即 Django 后台设置的 Client id
- oauth2 client secret:即 Django 后台设置的 Client secret
- oauth2 authorize url:Django 后台的 OAuth2 授权地址
- oauth2 token url:Django 后台获取 Token 的地址
其中 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 是否已验证等等。
随后,将相关字段填写到接下来的字段中即可。比如:
- oauth2 user json url:填写
https://YOUR_DJANGO_SITE/api/account/info
- oauth2 json user id path:填写
data.uid
- oauth2 json user name path:填写
data.username
- oauth2 json email path:填写
data.email
其余字段根据需要填写即可。
如果一切顺利,你的 Discourse 站点就可以使用 Django 站点的账号登录了。
评论: