Chrome 无法获取 localStorage

Posted

技术标签:

【中文标题】Chrome 无法获取 localStorage【英文标题】:Chrome is unable to get localStorage 【发布时间】:2021-08-04 02:18:45 【问题描述】:

我目前正在尝试制作一个脚本,您可以使用该脚本使用您的令牌自动登录不和谐。然而,当我尝试做window.localStorage.setItem("token", "value"); 它只是sais selenium.common.exceptions.javascriptException: Message: javascript error: Cannot read property 'setItem' of undefined。 那么如果window.localStorage 未定义,我该如何更改它并访问本地存储?

如果有帮助,这是我的完整代码:

from selenium import webdriver

token = input("Enter User Token:\n  -> ")

driver = webdriver.Chrome()
driver.get("https://www.discord.com/login")
driver.execute_script(f"window.localStorage.setItem('token', 'token');")
driver.refresh()

编辑: 我的最终代码可在this GitHub Repo 上找到。 (https://github.com/RealMoondancer/DiscordTokenLogin)

【问题讨论】:

总是将完整的错误消息(从单词“Traceback”开始)作为文本(不是截图,不是链接到外部门户)有问题(不是评论)。还有其他有用的信息。 脚本可能正在使用变量“localStorage”并且它已被初始化。尝试设置。使用 var localStorage = window.localStorage;然后 localStorage.setItem(... 我在其他页面上测试过,似乎只有这个页面没有window.localStorage。或者它可能出于安全原因阻止它。 如果有人想要我的最终代码,我在这里上传:github.com/RealMoondancer/DiscordTokenLogin 【参考方案1】:

我为其他页面测试了window.localStorage,只有这个页面没有。

在我找到的所有 JavaScript 文件中检查了单词 localStorage 之后

https://discord.com/assets/43c944f57ecd3f83e53c.js

delete window.localStorage

删除这个对象 - 这会产生问题。

我认为他们这样做是出于安全原因。

delete之前还有

r=window.localStorage

这可能意味着他们将其分配给变量 r 以保持访问权限,但此变量对我不起作用。可能他们稍后将其分配给其他变量,但代码被混淆了,我无法识别他们分配它的位置。


编辑:

在谷歌上查看后,我发现了类似的问题

Discord window.localStorage is undefined. How to get access to the localStorage on Discord page?

答案显示如何重新创建对localStorage 的访问权限。

// If we create an <iframe> and connect it to our document, its
// contentWindow property will return a new Window object with
// a freshly created `localStorage` property. Once we obtain the
// property descriptor, we can disconnect the <iframe> and let it
// be collected — the getter function itself doesn’t depend on
// anything from its origin realm to work**.

function getLocalStoragePropertyDescriptor() 
  const iframe = document.createElement('iframe');
  document.head.append(iframe);
  const pd = Object.getOwnPropertyDescriptor(iframe.contentWindow, 'localStorage');
  iframe.remove();
  return pd;


// We have several options for how to use the property descriptor
// once we have it. The simplest is to just redefine it:

Object.defineProperty(window, 'localStorage', getLocalStoragePropertyDescriptor());

window.localStorage.heeeeey; // yr old friend is bak

// You can also use any function application tool, like `bind` or `call`
// or `apply`. If you hold onto a reference to the object somehow, it
// won’t matter if the global property gets deleted again, either.

const localStorage = getLocalStoragePropertyDescriptor().get.call(window);

当我在 JavaScript 控制台中测试它时,这对我有用(对于页面 discord.com


编辑:

最少的工作代码。

from selenium import webdriver
import time

def test1(driver, url, token='abc'):

    print('[test1] url:', url) 
    driver.get(url)

    time.sleep(1)

    try:
        driver.execute_script(f"window.localStorage.setItem('token', 'token');")
        driver.refresh()

        print('[test1] get token:', driver.execute_script(f"return window.localStorage.getItem('token');") )
    except Exception as ex:
        print('[Exception]', ex)
        
def test2(driver, url, token='abc'):
    recreate_localStorage_script = '''
    const iframe = document.createElement('iframe');
    document.head.append(iframe);
    const pd = Object.getOwnPropertyDescriptor(iframe.contentWindow, 'localStorage');
    iframe.remove();    
    Object.defineProperty(window, 'localStorage', pd);
    '''

    print('[test2] url:', url) 
    driver.get(url)

    time.sleep(1)
    
    try:
        driver.execute_script(recreate_localStorage_script)
        driver.execute_script(f"window.localStorage.setItem('token', 'token');")
        driver.refresh()

        driver.execute_script(recreate_localStorage_script)
        print('[test2] get token:', driver.execute_script(f"return window.localStorage.getItem('token');") )
    except Exception as ex:
        print('[Exception]', ex)

if __name__ == '__main__':
    token = 'abc'

    driver = webdriver.Chrome()
    #driver = webdriver.Firefox()  # raise error when you try to use localStorage: "SecurityError: The operation is insecure."
                                  # selenium.common.exceptions.JavascriptException: Message: SecurityError: The operation is insecure.

    test1(driver, "https://httpbin.org/get", token)    # OK
    test1(driver, "https://***.com", token)  # OK if it sleeps few (milli)seconds
    test1(driver, "https://discord.com/login", token)  # ERROR

    test2(driver, "https://httpbin.org/get", token)    # OK
    test2(driver, "https://***.com", token)  # OK
    test2(driver, "https://discord.com/login", token)  # OK

顺便说一句:

当我尝试在 Firefox 中使用 localStorage 时,它会引发错误

 selenium.common.exceptions.JavascriptException: 
 Message: SecurityError: The operation is insecure.

它可能需要其他东西来解决这个问题。


编辑:

对于其他访问者:正如@Moondancer 在评论中提到的那样,如果token 像这样在" " 中,它就可以工作

driver.execute_script(f"window.localStorage.setItem('token', '\"token\"');")

【讨论】:

我添加了用于测试问题的最小工作示例。 顺便说一句,如果您想登录不和谐,您必须将driver.execute_script(f"window.localStorage.setItem('token', 'token');") 更改为driver.execute_script(f"window.localStorage.setItem('token', '\"token\"');"),因为该值必须在“”中。 你做到了吗?你用 localStorage 登录了吗? 是的,我已经使用 localStorage 成功登录。只需将令牌添加为值 sorroundet by "" 并作为键使用 token 并刷新站点。 我将此信息添加到回答中,以便其他访问者看到它。

以上是关于Chrome 无法获取 localStorage的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 无法获取 localStorage

获取 API:无法使用 Chrome 对请求标头添加授权

为啥 chrome xpath 插件获取后无法定位

无法使用 chrome.bluetoothLowEnergy 从 iOS 外围设备获取服务

无法获取未定义或空引用的属性“应用”-IE11 和 Chrome

切换选项卡时,带有无头 chrome 的 Selenium 无法获取 url