Bio
1
您好,
我刚开始接触 Discourse 和 AWS,希望能得到大家的帮助或指引。我正在按照本论坛上的说明设置 DiscourseConnect 与我的网站集成:https://meta.discourse.org/t/discourseconnect-official-single-sign-on-for-discourse-sso/13045/1
在实际操作中,当我对 Base64 编码后的负载进行哈希计算时,得到的结果与签名不一致。
负载:bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=(已省略换行符)
签名:2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
我的 HMAC 哈希值(通过 devglan 在线工具生成):1ce1494f94484b6f6a092be9b15ccc1cdafb1f8460a3838fbb0e0883c4390471
当我为返回 URL 生成签名时,结果与网站一致,因此我不太明白为何负载的哈希结果不匹配。如果您能提供任何关于此问题的见解,我将不胜感激。
david
(David Taylor)
2
能否提供一个示例负载、你得到的哈希值以及密钥?(在发布到此处之前,请务必更改测试站点上的密钥)
换行符非常重要,会影响签名。看起来 HMAC-SHA256 Generator Online 在计算哈希之前会去除换行符。你可以尝试使用其他工具,例如 https://www.freeformatter.com/hmac-generator.html。
此外,你需要对 URL 编码后 的 base64 负载计算 HMAC。因此,你绝不应该计算包含原始换行符的负载的哈希值。
正确的做法是使用 %0A。如果你使用的是 Web 框架,请注意它可能会自动对负载进行解码。你需要找到一种方法来禁用此功能,或者重新编码该值。
3 个赞
Bio
3
我还没有在我的网站上测试过这个,在这样做之前,我正尝试手动理清步骤。
来自之前引用的论坛帖子:
给定以下设置:
Discourse 域名:http://discuss.example.com
DiscourseConnect URL:http://www.example.com/discourse/sso
DiscourseConnect 密钥:d836444a9e4084d5b224a60c208dce14
用户尝试登录
- 生成 Nonce:
cb68251eefb5211e58c00ff1395f0c0b
- 生成原始负载(Raw payload):
nonce=cb68251eefb5211e58c00ff1395f0c0b
- 对负载进行 Base64 编码:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\n
- 对负载进行 URL 编码:
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI%3D%0A
- 对 Base64 编码后的负载生成 HMAC-SHA256:
2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56
在这里我得到了不同的结果。当我使用你建议的 HMAC 编码器对未进行 URL 编码的 Base64 负载进行处理时,我得到的是 d26d5adf900de48890a0c3dcdeec108acd91b44a4b76c90c59955a5ba7b957f7,而不是 2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56。当我对 URL 编码后的负载使用它时,我得到的是 46e749cd26dcabc84eed323ff31f830da674dc87c77a2fcb1b296f76402ea900。
然而,在教程的后面部分,在创建新负载时:
生成未签名的负载:
nonce=cb68251eefb5211e58c00ff1395f0c0b&name=sam&username=samsam&email=test%40test.com&external_id=hello123&require_activation=true
(顺序不重要,值已进行 URL 编码)
对负载进行 Base64 编码
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ==
对负载进行 URL 编码
bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGImbmFtZT1zYW0mdXNlcm5hbWU9c2Ftc2FtJmVtYWlsPXRlc3QlNDB0ZXN0LmNvbSZleHRlcm5hbF9pZD1oZWxsbzEyMyZyZXF1aXJlX2FjdGl2YXRpb249dHJ1ZQ%3D%3D
对 Base64 编码后的负载进行签名
3d7e5ac755a87ae3ccf90272644ed2207984db03cf020377c8b92ff51be3abc3
这个签名是通过对未进行 URL 编码的 Base64 负载进行哈希生成的,这就是为什么我对它为什么在第一个负载上不起作用感到有些不确定。
david
(David Taylor)
4
有趣!我也无法使用该在线生成器重现签名。在 Ruby 中,我可以这样做,结果符合预期:
pry(main)> OpenSSL::HMAC.hexdigest("sha256", "d836444a9e4084d5b224a60c208dce14", "bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\n")
=> "2828aa29899722b35a2f191d34ef9b3ce695e0e6eeec47deb46d588d70c7cb56"
出于直觉,我尝试为末尾带有回车符和换行符(即 Windows 风格的行尾)的字符串生成签名,结果成功获得了与 freeformatter.com 工具相同的签名:
pry(main)> OpenSSL::HMAC.hexdigest("sha256", "d836444a9e4084d5b224a60c208dce14", "bm9uY2U9Y2I2ODI1MWVlZmI1MjExZTU4YzAwZmYxMzk1ZjBjMGI=\r\n")
=> "200c03f1e5d7b859170be102b436d74f761040261be9682b4afec67eb908fabf"
因此,我认为最好的办法是避开这些在线工具,尝试在您将要使用的任何编程语言中实现一个最小化的方案。
6 个赞
Bio
5
感谢您的建议!我用 JavaScript 编写了部分流程,并在 RunKit 中使用 nodeForge、urlencode 和 js-base64 库进行测试,结果与教程一致。
3 个赞