最近分配给我的一个学校项目有一个编码挑战,我们必须完成。挑战有多个部分,最后一部分是上传到私人GitHub回购,并在特定条件下通过POST请求提交完成请求。
我已经成功完成了挑战的其他部分,并坚持提交请求。提交必须遵循以下规则:
构建您的解决方案请求
首先,构造一个JSON字符串,如下所示:
{
nbsp nbsp;
"github_url": "https://github.com/YOUR_ACCOUNT/GITHUB_REPOSITORY",
nbsp nbsp;
"contact_email": "YOUR_EMAIL"
}
在
YOUR_EMAIL
中填写您的电子邮件地址,并在YOUR_ACCOUNT/GITHUB_REPOSITORY
中填写包含您的解决方案的私人Github存储库。然后,使用JSON字符串作为正文部分,向以下URL发出HTTPPOST请求。
CHALLENGE_URL
内容类型
请求的Content-Type:必须为
application/json
。授权
URL受HTTP基本身份验证保护,RFC2617第2章对此进行了解释,因此您必须在POST请求中提供Authorization:header字段。
- 对于HTTP基本身份验证的userid,请使用与JSON字符串中相同的电子邮件地址
- 对于密码,提供符合RFC6238的10位基于时间的一次性密码TOTP
授权密码
要生成TOTP密码,您需要使用以下设置:
- 您必须根据RFC6238生成正确的TOTP密码
- TOTP的
Time Step X
为30秒。CCD_ 10为0- 使用
HMAC-SHA-512
作为哈希函数,而不是默认的HMAC-SHA-1
- 令牌共享机密是用户ID后面跟着ASCII字符串值
"APICHALLENGE"
(不包括双引号(共享机密示例
例如,如果用户ID是
"email@example.com"
,则令牌共享机密是"email@example.comAPICHALLENGE"
(不带引号(。如果POST请求成功,服务器将返回HTTP状态代码200。
我试着非常仔细地遵循这个大纲,并以不同的方式测试我的工作。然而,我似乎做不好。我们应该从Node服务器后端发出请求。这就是我迄今为止所做的。我用npm init
创建了一个新的npm项目,并安装了您将在下面的代码中看到的依赖项:
const axios = require('axios');
const base64 = require('base-64');
const utf8 = require('utf8');
const { totp } = require('otplib');
const reqJSON =
{
github_url: GITHUB_URL,
contact_email: MY_EMAIL
}
const stringData = JSON.stringify(reqJSON);
const URL = CHALLENGE_URL;
const sharedSecret = reqJSON.contact_email + "APICHALLENGE";
totp.options = { digits: 10, algorithm: "sha512" }
const myTotp = totp.generate(sharedSecret);
const isValid = totp.check(myTotp, sharedSecret);
console.log("Token Info:", {myTotp, isValid});
const authStringUTF = reqJSON.contact_email + ":" + myTotp;
const bytes = utf8.encode(authStringUTF);
const encoded = base64.encode(bytes);
const createReq = async () =>
{
try
{
// set the headers
const config = {
headers: {
'Content-Type': 'application/json',
"Authorization": "Basic " + encoded
}
};
console.log("Making req", {URL, reqJSON, config});
const res = await axios.post(URL, stringData, config);
console.log(res.data);
}
catch (err)
{
console.error(err.response.data);
}
};
createReq();
据我所知,我不确定自己在哪里犯了错误。我在理解这些要求时尽量小心谨慎。我简要查看了挑战概述的所有文件,并收集了在给定条件下正确生成TOTP所需的必要要求。
我发现npm包otplib
可以通过我传递的选项满足这些要求。
然而,我的解决方案是不正确的。当我尝试提交解决方案时,我会收到错误消息"Invalid token, wrong code"
。有人能帮我看看我做错了什么吗?
我真的不希望我所有的努力都是徒劳的,因为这是一个漫长的项目。
提前非常感谢您在这方面的时间和帮助。我非常感激。
包otplib
的Readme状态:
// TOTP defaults
{
// ...includes all HOTP defaults
createHmacKey: totpCreateHmacKey,
epoch: Date.now(),
step: 30,
window: 0,
}
因此epoch (T0)
的默认值是Date.now()
,这是RFC标准。任务描述定义T0
为0
。
您需要将epoch
的默认值更改为0
:
totp.options = { digits: 10, algorithm: "sha512", epoch: 0 }