Javascript 如何使用Greasemonkey从远程域获取cookie?

Javascript 如何使用Greasemonkey从远程域获取cookie?,javascript,cookies,greasemonkey,gm-xmlhttprequest,Javascript,Cookies,Greasemonkey,Gm Xmlhttprequest,我正在写一个Greasemonkey(v2.3)脚本,它基本上是在屏幕上刮取所提供的内容,因为缺少任何类型的API 问题是,我想从谷歌翻译,一个不同的领域查询这个URL。为此,我可以毫无问题地使用GM_xmlhttpRequest,但对特定URL的GET请求(例如)会生成一个带有隐藏表单的HTML页面,该页面在调用challenge()javascript函数后发布,该函数会计算在POST请求中传递的某种令牌 显然,这是异步发生的,Greasemonkey对此一无所知。通过反复试验,我意识到如果

我正在写一个Greasemonkey(v2.3)脚本,它基本上是在屏幕上刮取所提供的内容,因为缺少任何类型的API

问题是,我想从谷歌翻译,一个不同的领域查询这个URL。为此,我可以毫无问题地使用GM_xmlhttpRequest,但对特定URL的GET请求(例如)会生成一个带有隐藏表单的HTML页面,该页面在调用
challenge()
javascript函数后发布,该函数会计算在POST请求中传递的某种令牌

显然,这是异步发生的,Greasemonkey对此一无所知。通过反复试验,我意识到如果我的浏览器(Iceweasel 31.2.0)有一个lema.drae.es的cookie,那么使用
GM_xmlhttpRequest
发出的GET请求实际上会返回我想要的内容,即作为URL中的参数“val”传递的单词定义的HTML。但是,如果我删除lema.drae.es的所有cookie,GET请求将返回前面提到的隐藏表单

简言之,我需要一种从Greasemonkey内部接收POST请求响应的方法,我相信如果能够从服务器接收cookie并将其存储,那么我可以将其作为请求头包含在进一步的请求中,并且它应该按照我的预期工作。或者它应该简单地存储在浏览器中,因此当我触发
GM_xmlhttpRequest
时,它将作为头发送

我尝试了一种不同的解决方案来解决我的问题,也就是说,浏览器基于同源策略阻止了iframe的创建,即使在将userscript配置为在两个域上运行之后也是如此

希望我已经明确了我想要实现的目标,我希望有人能为我指明正确的方向


附带说明:如果有人能解释一下
challenge()
函数的计算方法,我会非常感激。我的假设是,它生成的令牌会被发送到服务器,服务器反过来使用它来生成cookie,但这听起来太复杂了……

隐藏的iframe路由是可行的,但在这种情况下,translate.google.com会阻止它

以下是另一种方法,以确保Firefox拥有使您的mashup站点()满意所需的新鲜cookie:

  • 查找mashup站点需要新鲜cookie时出现的一些源HTML,但在其他情况下不存在这些源HTML。
    在这种情况下,JS源代码
    函数挑战就可以了

  • 对mashup站点执行
    GM\u xmlhttpRequest
    ,并测试响应

  • 如果GM_xmlhttpRequest响应具有所需数据,请根据需要对其进行分析。
    完成了

  • 如果GM_xmlhttpRequest响应具有“需要cookies”源,请在弹出窗口中打开mashup站点的特殊查询:

  • 由于该站点是在自己的窗口中打开的,因此不会被跨源安全措施阻止
  • 将GM脚本设置为也对该特殊URL进行操作
  • 对于特殊URL,请等待,直到出现指示页面已完成加载并设置cookie的关键节点或文本
  • 一旦弹出窗口完成,它会向打开的页面发送一条消息,然后自动关闭
  • 当开始页面收到消息时,它会重新请求mashup页面
  • 解析它并完成

  • 下面是一个完整且经过测试的Greasemonkey脚本(在Firefox上),它将lema.rae.es/drae/srv/search混合到translate.google.com中:


    啊,我明白了。非常感谢你的回答!除了需要创建和关闭一个实际的选项卡,以及随之而来的flicking之外,这一点效果相当不错。我猜这是没办法的,是吗?你说的iframe被translate.google.com屏蔽是什么意思?你的意思是因为mashup站点位于另一个域而被阻止创建它吗?另外,你知道
    challenge()
    javascript函数在无cookie场景中做了什么吗?不,对于Google translate,除非您编写自己的浏览器扩展,否则无法避免额外的选项卡,这将比userscript方法困难得多。。。在你的Q中,你说,“
    浏览器基于同源策略阻止了iframe的创建…
    ”,这是真的。但这种行为是由各自的服务器控制的
    lema.rae.es
    不会阻止它,而是让它自己在其他几个域上构建。在这种情况下,Google正在阻止iframe。函数
    challenge()
    从服务器获取自定义数据并生成自定义会话cookie。理论上,您可以尝试获取这些数据并生成自己的cookie,并尝试复制“握手”序列,但这比我的答案中的方法更加混乱,如果不需要编写新的FF附加组件,可能无法工作。
    // ==UserScript==
    // @name     _GM_xmlhttpRequest that needs cookie(s)
    // @include  https://translate.google.com/*
    // @include  http://lema.rae.es/drae/srv/search?val=openedByGM
    // @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
    // @grant    GM_xmlhttpRequest
    // ==/UserScript==
    
    //--- Global variables
    var mashupURL   = "http://lema.rae.es/drae/srv/search?val=test";
    var cookGenURL  = "http://lema.rae.es/drae/srv/search?val=openedByGM";
    
    if (location.href == cookGenURL) {
        //--- May be best we can do until Greasemonkey fixes tab handling flaws.
        document.title = "Close me!";
    
        if (window.opener) {
            waitForKeyElements ("i:contains(openedByGM)", closePopupIfCan);
        }
    }
    else {
        attemptMashup ();
    
        window.addEventListener ("message", receiveCookieMessage, false);
    }
    
    //-- Just functions from here on down...
    
    function closePopupIfCan (jNode) {
        window.opener.postMessage ("Cookie(s) should be set!", "*");
        window.close ();
    }
    
    function attemptMashup () {
        GM_xmlhttpRequest ( {
            method:     "GET",
            url:        mashupURL,
            onload:     parseDictionaryResponse,
            onabort:    reportAJAX_Error,
            onerror:    reportAJAX_Error,
            ontimeout:  reportAJAX_Error
        } );
    }
    
    function receiveCookieMessage (event) {
        if (event.origin != "http://lema.rae.es")     return;
    
        console.log ("message ==> ", event.data);
    
        /*--- Now that have cookie(s), re-attempt mashup, but need a little
            settling time.
        */
        setTimeout (attemptMashup, 888);
    }
    
    function parseDictionaryResponse (respObject) {
        if (respObject.status != 200  &&  respObject.status != 304) {
            reportAJAX_Error (respObject);
            return;
        }
        /*--- If the required cookie is not present/valid, open the target page
            in a temporary tab to set the cookies, then reload this page.
    
            The test string is unique to the scraped site and is only present
            when cookie(s) is/are needed.
        */
        if (/function\s+challenge/i.test (respObject.responseText) ) {
            var newTab  = window.open (cookGenURL);
            return;
        }
    
        //--- Don't use jQuery to parse this!
        var parser      = new DOMParser ();
        var responseDoc = parser.parseFromString (
            respObject.responseText, "text/html" // Firefox only, for now.
        );
    
        //--- Get site-specific payload and put in site-specific location.
        var payload     = responseDoc.querySelectorAll ("body > div");
        $("#gt-form-c").before (payload);
    }
    
    function reportAJAX_Error (respObject) {
        alert (
            'Error ' + respObject.status + '!  "' + respObject.statusText + '"'
        );
    }