背景
B 站专栏目前只支持富文本编辑器,文本编辑器就分为两种,支持 markdown 的和不支持 markdown,可惜的是 B 站的专栏并不支持 markdown 而且也没有计划支持,这也是可以理解,毕竟 up 主们并不都了解 markdown,但对于一个重度 md 用户,用富文本编辑器是无论如何都无法忍受的,于是研究了下专栏的逻辑,找到了支持 md 的方案,见下文。
分析
用户在编辑专栏时,系统会实时将数据通过接口 https://api.bilibili.com/x/article/creative/draft/addupdate
保存到后台,接口参数如下(curl)
curl 'https://api.bilibili.com/x/article/creative/draft/addupdate' \
-H 'authority: api.bilibili.com' \
-H 'accept: application/json, text/javascript, */*; q=0.01' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36' \
-H 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \
-H 'origin: https://member.bilibili.com' \
-H 'sec-fetch-site: same-site' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://member.bilibili.com/article-text/home?aid=74916' \
-H 'accept-language: zh,en;q=0.9,en-US;q=0.8,zh-CN;q=0.7,nb;q=0.6,mt;q=0.5' \
-H $'cookie: xxxxxxxxx(cookie 打码)' \
--data-raw 'title=%E8%BF%99%E6%98%AF%E6%A0%87%E9%A2%98&banner_url=&content=%3Cp%3E%E8%BF%99%E6%98%AF%E6%AD%A3%E6%96%87%3C%2Fp%3E&summary=%E8%BF%99%E6%98%AF%E6%AD%A3%E6%96%87&words=4&category=4&list_id=0&tid=4&reprint=0&tags=&image_urls=&origin_image_urls=&dynamic_intro=&media_id=0&spoiler=0&original=0&aid=74916&csrf=027817004f35eb34f312464c4828ca62' \
--compressed
可以看出以下几个信息
- 通过 form 形式提交到后台,从
content-type: application/x-www-form-urlencoded
可以看出
几个比较重要的参数:
- title:文章标题
- content:文章内容
- aid:文章编号
- csrf:csrf 编号,防止 csrf 攻击
- 接口返回值如下
{"code":0,"message":"0","ttl":1,"data":{"aid":74916}}
看到这里聪明的你就能发现可以自己伪造一个 form 表单进行提交,于是简单写了个表单 html
<html>
<body>
<form action="https://api.bilibili.com/x/article/creative/draft/addupdate" method="POST">
<input type="text" name="content" id="bcontent" value="测试是否可以通过伪造表单进行提交"/>
<input type="text" name="aid" id="baid" value="74916"/>
<input type="text" name="csrf" id="bcsrfid" value="027817004f35eb34f312xxxxxxxx"/>
<input type="submit" value="提交" />
</form>
</body>
</html>
提交后返回 code:0 说明提交成功,进入 B 站后台专栏管理,确实修改成功
如果没有 csrf 这个编号那么这个 demo 就是赤裸裸的 csrf 攻击
demo 测试成功于是方案就很好做。
实现
大概的思路是通过 js 将 markdown 转换为 html,再通过上述的表单进行提交,但用户需要提供一些必要的信息。markdown 转 js 这里通过 showdown 库实现。代码也不多,这里贴出完整源码,另存为 html 即可
<html>
<head>
<meta name="referrer" content="unsafe-url" />
<meta name="referrer" content="origin" />
<meta name="referrer" content="no-referrer-when-downgrade" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="referrer" content="no-referrer" />
<meta charset="utf-8" />
</head>
<body style="margin-top:20px;margin-left:20px;">
<h2><a target="_blank" href="http://zhengjianfeng.cn" style="color:blue"> 帮助文档!!!!!!!</a></h2>
<p>aid:</p><input type="text" name="aid" id="aid" value="74916"/></br>
<p>csrfid:</p><input type="text" name="csrfid" id="csrfid" style="width:250px" value="027817004f35eb34f312464c4828ca62"/></br>
<p>markdown 内容:</p>
<textarea rows="20" cols="100" id="md"></textarea></br></br>
<button onclick="submitForm();"> 提交 </button>
<form id="bform" action="https://api.bilibili.com/x/article/creative/draft/addupdate" method="POST">
<input type="hidden" name="content" id="bcontent" value="xxxx"/>
<input type="hidden" name="aid" id="baid" value="74916"/>
<input type="hidden" name="csrf" id="bcsrfid" value="027817004f35eb34f312xxxxxxxx"/>
</form>
<script src="showdown.js"></script>
<script type="text/javascript">
function submitForm(){var aid = document.getElementById("aid").value;
var csrfid=document.getElementById("csrfid").value;
document.getElementById("baid").value=aid;
document.getElementById("bcsrfid").value=csrfid;
var content=document.getElementById("md").value;
var converter = new showdown.Converter();
var htmlcontent = converter.makeHtml(content);
document.getElementById("bcontent").value=htmlcontent;
document.getElementById("bform").submit();}
</script>
</body>
</html>
界面如下:
用户需要提供参数 aid
和csrfid
,这两个参数可以通过以下方式获取
- 打开网络调试工具,一般浏览器步骤就是 打开开发者工具(F12)- 切换到网络,在专栏富文本随便输入一些内容,这时候在调试窗口就能看到调用保存接口
addupdate
这里面就包含所需参数
在线版
这里已经将页面部署到阿里云上方便大家使用,地址:http://zhengjianfeng.cn/bilibili/
问题答疑
- 提交失败,出现以下错误
原因:当前浏览器不支持 no-referrer
功能,可以使用 chrome 或者 firefox 进行访问
- 出现以下错误
{"code":-111,"message":"csrf 校验失败","ttl":1}
原因:未登录 B 站或者已经退出,重新登录,根据以上方式获取最新的 csrf,csrf 每次登录都不一样