所有的 onedrive 账户中,无管理员类型的 OneDrive 是最安全的,但是另外一方面,无管理员也不能调用 graph api,使用起来也不太方便。
除了这类原本就没有管理员账户的,还有一种是管理员为了防止滥用,特地关闭 onedrive api 的。无论哪一种,二者都不能使用 graph api,但是,他们都是可以调用 sharepoint api。
基本原理
利用 onedrive 分享可以获得一个免登录的分享链接,点击此链接会获得一个 cookie,利用此 cookie 可以获取 sharepoint 的 api_url 和 access_token。然后就可以调用了 sharepoint 的 api 了。
获取分享链接
参考此篇 https://www.onesrc.cn/p/onedrive-for-onepoint-configuration.html
eg:https://lovelearn-my.sharepoint.com/:f:/g/personal/admin_share_onesrc_cc/Es6CMetI4fJCr4GqWZ3uvA0BEnzJxxb4CU-iQr04VYomLQ?e=C9K35U
获取 cookie 和 access_token
注:下文出现的 lovelearn-my.sharepoint.com
和 admin_share_onesrc_cc
需要根据自己的实际情况进行替换。
通过 shareurl 获取 cookie:
GET https://lovelearn-my.sharepoint.com/:f:/g/personal/admin_share_onesrc_cc/Es6CMetI4fJCr4GqWZ3uvA0BEnzJxxb4CU-iQr04VYomLQ?e=C9K35U
响应头中含有 cookie 信息,提取出来即可。
Set-Cookie: FedAuth=xxx; path=/; secure; HttpOnly
再利用 cookie,向特定链接发送 post 请求。
POST https://lovelearn-my.sharepoint.com/personal/admin_share_onesrc_cc/_api/web/GetListUsingPath(DecodedUrl=@a1)/RenderListDataAsStream?@a1='%2Fpersonal%admin_share_onesrc_cc%2FDocuments'&RootFolder=%2Fpersonal%admin_share_onesrc_cc%2FDocuments%2F&TryNewExperienceSingle=TRUE
Accept: application/json;odata=verbose
Content-Type: application/json;odata=verbose
origin: https://lovelearn-my.sharepoint.com
Cookie: FedAuth=xxx; path=/; SameSite=None; secure; HttpOnly
{"parameters":{"__metadata":{"type":"SP.RenderListDataParameters"},"RenderOptions":136967,"AllowMultipleValueFilterForTaxonomyFields":true,"AddRequiredFields":true}}
响应数据为 json,在响应里面ListSchema['.driveAccessToken']
和 ListSchema['.driveUrl']
,这两个就是 我们需要的 access_token 和 api_url 。
如何使用
传统的 graph api 接口不变,我们在使用时只需将 api_url 替换为上面获得的 driveUrl 即可,用 driveAccessToken 替代 http header 中的 Authorization 部分即可。
同时,我们的 shareurl 和 cookie 就相当于是 refresh token,可以用它来获得 access_token。
GET ${api_url}/root/children
Accept: application/json, text/plain, */*
Authorization: Bearer ${access_token}
兼容性
office官网文档 有说明 https://graph.microsoft.com/v1.0/ 和 https://{tenant-name}.sharepoint.com/_api/v2.0/sites
是等价的,原有的 graph api 在这里都能使用,所以基本不同担心兼容性啥的。
有一点非常重要的区别是下载链接不再是用@microsoft.graph.downloadUrl
而是换成了 @content.downloadUrl
。
其他的像新建文件夹、上传文件、删除文件、移动文件等都可以正常使用。
onepoint 已经实现了这些,有兴趣的可以自行体验。
本文由 ukuq 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Mar 27, 2020 at 06:12 pm
大佬这个方法可以在alist挂载无管理员校园账户的onedrive/sharepoint吗?我现在使用的webdav挂载的,但是它有2G文件大小的限制。
没有限制,这个是模拟官方的网页。但估计alist上没人做过这个对接api
或者挂载rclone也可以
谢谢回复,大佬有思路吗?我自己折腾个试试。
自己登录获取的Auth换Token,到是权限齐全,但是世纪互联不返回Token,难道世纪互联不一样,还是说我搞得不对?
https://universitytongji-my.sharepoint.cn/personal/xxx_alumni_tongji_edu_cn/_api/web/GetList(@listUrl)/RenderListDataAsStream?@listUrl='/personal/xxx_alumni_tongji_edu_cn/Documents'&TryNewExperienceSingle=TRUE
不知道博主有没有测试过世纪互联呢?
世纪互联刚刚试过了, 不行。如果你要是拿来做oneindex之类的,我可以推荐你参考这个 https://github.com/ukuq/onepoint/blob/master/lib/sharepointAPI.js
这里面是完全在模拟正常的点击操作。不过由于上传api太麻烦,就没有做适配,仅仅实现了文件列表功能,且每次最多列出200文件。
我已经简单挪到了rclone上,还行:https://github.com/nickfox-taterli/rclone
世纪互联我看了看是V1.0的sharepoint,估计API WRAPPER要重写一个.
搞了很久还是不行,能列文件不能上传,不管怎么设置分享连接,上传都无效.
如果博主方便的话能做一个LINUX SHELL下的上传程序或者类似的就好了,下面是我测试的创建目录代码没办法完成.提示权限不够,
# 列文件 headers = { 'Authorization': 'Bearer ' + token } response = requests.get(api_url + 'root/children', headers=headers) print(json.loads(response.text)) # 创建目录 headers = { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' } payload = { "name": 'Test1', "folder": {}, "@microsoft.graph.conflictBehavior": "fail" } response = requests.post(api_url + 'items/' + folder_id + '/children', headers=headers, data=json.dumps(payload)) print(json.loads(response.text))
要看具体报错才行, 分享的时候有勾选允许任何人编辑吗?
https://pastebin.com/DaE9SJeB
提示就是{'error': {'code': 'accessDenied', 'message': 'Access denied'}}
权限是Anyone with the link can edit
如果你想要用文件管理的api, 可以自己登录账号, 抓那个里面的 cookie 和 access token, 那个权限更强一点, 不过就是要定期更新 cookie 就是了.
微软限制了分享的链接只能上传和列表权限, 不能新建文件夹 文件删除之类的.
确实只有上传,下载,列文件,和Web上一样.
进行POST后,似乎出现这个问题,搞了好久还是没搞懂,不知道博主能看出是什么毛病吗?
-1, Microsoft.Data.OData.ODataException The property '__metadata' does not exist on type 'SP.RenderListDataParameters'. Make sure to only use property names that are defined by the type.
解决了,竟然是UA问题...
Postman的UA不行,伪造UA解决.
这个很实用啊,但是这个分享链接貌似是有有效期的,过期了应该还要重新获取吧
可以设置为永不过期