3

Discourse 集成 Django 登录

 1 year ago
source link: https://oldj.net/article/2023/06/27/discourse-with-django-oauth2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近搭建了一个 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 插件的设置按钮可进入对应的设置页面。

discourse-oauth2_01.png

当然,你也可以在总设置的“登录”面板下看到相关的设置,不过那个面板选项很多,如果只想设置 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 urloauth2 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 pathoauth2 callback user info paths 留空或使用默认值即可。

再下面则是 oauth2 fetch user details 相关的字段,你需要先在 Django 站点准备好一个页面,比如页面为 https://YOUR_DJANGO_SITE/api/account/info,返回内容形如:

{
  "data": {
    "uid": "xxx",
    "username": "my_name",
    "email": "[email protected]"
    // ......
  }
}

还可以添加更多字段,比如用户全名、头像图片地址、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 站点的账号登录了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK