syhyz1990 / baiduyun

油猴脚本 - 一个免费开源的网盘下载助手
https://www.youxiaohou.com/install.html
GNU Affero General Public License v3.0
3.18k stars 392 forks source link

度盘的临时解决方案 #383

Closed lvzhenbo closed 1 month ago

lvzhenbo commented 2 months ago

在度盘开放平台申请APP KEY

因为APP KEY是油小猴作者通过自己网站接口获得的,所以这里就不放抓包到的APP KEY了,自己去申请 度盘开放平台 创建应用获取KEY

获得access_token

浏览器调用这个链接

http://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=这里替换成你的AppKey&redirect_uri=oob&scope=basic,netdisk

你会获得类似下面这个链接

https://openapi.baidu.com/oauth/2.0/login_success#expires_in=2592000&access_token=这里是获得的access_token&session_secret=&session_key=&scope=basic+netdisk

修改脚本879-900行

            //let res = await base.getFinalUrl(pan.pcs[3]);
            //if (res.indexOf('access_token') === -1) {
                //let html = await base.get(pan.pcs[3], {}, 'text');
                //let bdstoken = html.match(/name="bdstoken"\s+value="([^"]+)"/)?.[1];
                //let client_id = html.match(/name="client_id"\s+value="([^"]+)"/)?.[1];
                //let data = {
                    //grant_permissions_arr: 'netdisk',
                    //bdstoken: bdstoken,
                    //client_id: client_id,
                    //response_type: "token",
                    //display: "page",
                    //grant_permissions: "basic,netdisk"
                //}
                //await base.post(pan.pcs[3], base.stringify(data), {
                    //'Content-Type': 'application/x-www-form-urlencoded',
                //})
                //let res2 = await base.getFinalUrl(pan.pcs[3]);
                //let accessToken = res2.match(/access_token=([^&]+)/)?.[1];
                //accessToken && base.setStorage('accessToken', accessToken);
                //return accessToken;
            //}
            let accessToken = 这里填入你的access_token;

无法使用具体原因

可以从access_token的回调链接看出,度盘将参数放到了hash里导致单纯的url get调用无法获得,只能通过window.location.hash在对应页面获得

Gentran commented 2 months ago

No need to modify the script. You can just fill it in the accessToken in local storage of pan.baidu.com.

lvzhenbo commented 2 months ago

Oh, that's right, thanks for the reminder. Then I discussed it with a friend on my side and he found out that it can be solved by loading an iframe 哦,是这样啊,感谢提醒。然后我这边和朋友讨论,他发现了可以通过加载iframe去解决

const iframe = document.createElement('iframe');
iframe.src = 'https://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=xxx&scope=basic,netdisk&redirect_uri=oob';
iframe.style.display = 'none';
document.body.appendChild(iframe);
setTimeout(()=>console.log(new URL(iframe.baseURI).hash), 1000);
Gentran commented 2 months ago

I tried iframe solution. Baidu will verify the Domain option of your app. Below is the error information from Baidu.

您遇到了错误!

. 错误代码:referer_mismatch
. 错误信息:Invalid Referer
. 详细描述:当前页面的Referer错误。使用Implicit Grant方式获取Access Token时,Referer必须与应用的根域名绑定同域,请在开发者在应用安全设置中进行绑定。

提示:为了保障账号安全,请认准本页URL地址必须以openapi.baidu.com开头
lvzhenbo commented 2 months ago

Then it looks like the only way is through GM_openInTab and GM_setValue. 那看样子只有通过GM_openInTab和GM_setValue这种方式了

Dragon1573 commented 2 months ago

Announcement: Due to the optimization and upgrade of the open platform, the creation of personal applications is temporarily suspended. The specific resumption time will be notified on the official website.

image

Originally posted in manual

It seems personal account are not permitted to access Baidu Net Disk Open Platform 😞

lvzhenbo commented 2 months ago

好吧,那没有APPID的就用作者的吧 我也不放出来,给个截图,会的就知道了 image

Dragon1573 commented 2 months ago

@lvzhenbo Nice ~ 👍🏼 Successfully set by manually invoke following statement in the console ❤️

localStorage.setItem("accessToken", my_access_token)
Dragon1573 commented 2 months ago

I made it!!! 🎉

Since v6.1.6 is not available from this repository, also I think the installable script is compiled from external TypeScript, I can't make a PR to fix this problem.

This is how I resolve the issue.

// This is line 260
        getFinalUrl(url, headers) {
            return new Promise((resolve, reject) => {
                let requestObj = GM_xmlhttpRequest({
                    method: "GET", url, headers,
                    onload: (res) => {
-                       resolve(res.finalUrl);
+                       let responseHeaders = res.responseHeaders.split("\n");
+                       let locationHeader = responseHeaders.filter((header) => header.startsWith("location"))[0];
+                       resolve(locationHeader.replace("location:", ""));
                    },
                    onerror: (err) => {
                        reject(err);
                    },
+                   redirect: "manual"
                });
            });
        },
// This is line 274

image image


@syhyz1990 - Hello :wave:

Could you please try apply this patch to version 6.1.7? :pray: I think it may help.

lvzhenbo commented 2 months ago

看样子问题解决了,不过好像是油猴对xhr和fetch有修补,我之前试了试拿不到header

KlparetlR commented 2 months ago

我成功了!!🎉

由于此存储库不可用,而且我认为可安装脚本是从外部 TypeScript 编译的,我无法制作 PR 来解决这个问题。v6.1.6

这就是我解决问题的方式。

// This is line 260
        getFinalUrl(url, headers) {
            return new Promise((resolve, reject) => {
                let requestObj = GM_xmlhttpRequest({
                    method: "GET", url, headers,
                    onload: (res) => {
-                       resolve(res.finalUrl);
+                       let responseHeaders = res.responseHeaders.split("\n");
+                       let locationHeader = responseHeaders.filter((header) => header.startsWith("location"))[0];
+                       resolve(locationHeader.replace("location:", ""));
                    },
                    onerror: (err) => {
                        reject(err);
                    },
+                   redirect: "manual"
                });
            });
        },
// This is line 274

image image

-你好 👋

您能否尝试将此补丁应用于版本 6.1.7?🙏 我认为这可能会有所帮助。

用你的改动成功解决了,非常感谢!

SSrFreak commented 2 months ago

参照内容编辑器里面改了一下,没有效果,删除掉重新安装了一次脚本就可以获取所有的内容了,什么情况?是版本更新了么?从新确认了一下脚本里的内容,还是原来未更改的内容,但是已经可以使用了。

dfvips commented 2 months ago

根据上面的改动,已正常使用。 image 可直接使用的脚本: https://cdn.jsdelivr.net/gh/dfvips/baiduyun/panlinker.user.js

I made it!!! 🎉

Since v6.1.6 is not available from this repository, also I think the installable script is compiled from external TypeScript, I can't make a PR to fix this problem.

This is how I resolve the issue.

// This is line 260
        getFinalUrl(url, headers) {
            return new Promise((resolve, reject) => {
                let requestObj = GM_xmlhttpRequest({
                    method: "GET", url, headers,
                    onload: (res) => {
-                       resolve(res.finalUrl);
+                       let responseHeaders = res.responseHeaders.split("\n");
+                       let locationHeader = responseHeaders.filter((header) => header.startsWith("location"))[0];
+                       resolve(locationHeader.replace("location:", ""));
                    },
                    onerror: (err) => {
                        reject(err);
                    },
+                   redirect: "manual"
                });
            });
        },
// This is line 274

image image

@syhyz1990 - Hello 👋

Could you please try apply this patch to version 6.1.7? 🙏 I think it may help.

根据上面的改动,已正常使用。 image 可直接使用的脚本: https://cdn.jsdelivr.net/gh/dfvips/baiduyun/panlinker.user.js

Dragon1573 commented 1 month ago

参照内容编辑器里面改了一下,没有效果,删除掉重新安装了一次脚本就可以获取所有的内容了,什么情况?是版本更新了么?从新确认了一下脚本里的内容,还是原来未更改的内容,但是已经可以使用了。

也许你在重装脚本之前成功地获取并配置了 accessToken ?只要它已经被保存到 localStorage 中,后续会直接使用这个已有值(它长期有效,不需要去刷新),这个问题就没法复现了。

目前已升级 v6.2.1 ,手动删除 accessToken 后再尝试此脚本依旧存在这个问题。

可直接使用的脚本:https://cdn.jsdelivr.net/gh/dfvips/baiduyun/panlinker.user.js

以上链接应该是把 Patch 打进去了,这个倒是有效的。

ybfed commented 1 month ago

对前端没什么认知的小白,表示看不太懂各位的代码 就是尝试了一下安装几个js脚本,网页端度盘的下载按钮依旧无法显示 看着帖子的时间好像已经几天的? 但我是刚刚才发现,大概24小时前还正常

ybfed commented 1 month ago

shit,我本想找个旧版试试,结果发现一个这个东西:(改)网盘直链下载助手 然后,就恢复正常了... 合着是6.2.1和我chrome版本不兼容之类的? 更新后导致下载按钮无法显示...

Prixii commented 1 month ago

解决了,看了下 api 文档,对比发现响应体的 file 字段是空的,推测是 accessToken 有误

通过上面给出的链接 http://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=这里替换成你的AppKey&redirect_uri=oob&scope=basic,netdisk 获得 accessToken 之后,通过 localStorage.setItem 覆盖

翻了下源码,可能是在有 accessToken 的时候就不会请求 oauth 接口更新,而 accessToken 有误也不会导致请求报错

Dragon1573 commented 1 month ago

解决了,看了下 API 文档,对比发现响应体的 file 字段是空的,推测是 accessToken 有误

其实并非 accessToken 有误,而是在没有预先设置它的情况下无法从接口返回的回调 URL 中解析出 Token 。

翻了下源码,可能是在有 accessToken 的时候就不会请求 OAuth 接口更新,而 accessToken 有误也不会导致请求报错

这个是的,只要设置了 accessToken 不管是否有效都不会再请求接口了,这个值是长期有效的,不需要去更新。

syhyz1990 commented 1 month ago

6.2.5 已修复