如何在注入代码中使用GM_xmlhttpRequest? [英] How to use GM_xmlhttpRequest in Injected Code?

查看:2664
本文介绍了如何在注入代码中使用GM_xmlhttpRequest?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个注入到网页中的用户脚本。该脚本从Web服务器读取一些数据,并且我想将消息发送到侦听应用程序以对数据作出反应。

现在,我所做的只是尝试向我的侦听应用程序发送一个字符串命令,看看我能否读取它。我的代码在它被注入之前工作,但是之后我得到一个未定义的引用错误。



我怀疑这与这个Greasemonkey访问违规。但是,我一直无法找到可行的解决方案。我正在使用Chrome进行开发。



以下是我无法工作的代码部分。



<$ $ {
method:POST,
url:http:// localhost:7777,
data:testing123,pre $ GM_xmlhttpRequest b $ b标题:{
Content-Type:application / x-www-form-urlencoded
},
onload:function(response)
{
if(response.responseText.indexOf(TEST)> -1)
{
console.log(Response confirm ...);
}
}
});

我对脚本编程很陌生,所以也许我错过了一些明显的东西。如何在注入代码中工作?

解决方案

GM _ 函数在注入的代码中不起作用,因为注入的代码在目标页面的作用域中运行。如果他们在那里工作,那么不道德的网站也可以使用 GM_ 功能 - 做出无法形容的邪恶。



解决方案,最优先考虑:


  1. 不要注入代码。很多时候,这确实没有必要,而且它总是使事情复杂化。如果你确实需要注入代码,肯定需要使用目标页面加载的一些JavaScript代码。

    对于像jQuery这样的库,使用 @require 指令(Firefox)或粘贴在库代码中或使用自定义 manifest.json 文件包括它(Chrome)。



    通过不注入代码,您可以:


    1. 保持轻松使用 GM _ 函数的功能

    2. 避免或减少对外部服务器提供库的依赖。 b $ b
    3. 避免页面JS上的潜在副作用和依赖项。 (您甚至可以使用像 NoScript 这样的内容在脚本仍然运行时完全禁用页面的JS。)

    4. 防止恶意网站利用脚本获取内容访问 GM _ 函数。




  2. 使用 Tampermonkey扩展(Chrome)。这允许您通过提供更好的Greasemonkey仿真来避免脚本注入。您可以使用 @require 指令和一个比Chrome本身提供的功能更强大/风险更高的版本 unsafeWindow


  3. 将您的用户代码分成注入部分 - 不能使用 GM _ 函数 - 以及未注入的部分。使用消息,轮询和/或特定的DOM节点在范围之间进行通信。










如果你确实必须使用注入代码,下面是一个示例脚本,显示了如何执行它:

  / / == UserScript == 
// @name _Fire注入代码中的GM_函数
// @include https://stackoverflow.com/*
// @grant GM_xmlhttpRequest
// == / UserScript ==
/ *警告:使用@match与@include可以杀死
GM_xmlhttpRequest的跨域功能!错误?
* /

函数InjectDemoCode($){
$(body)。prepend('< button id =gmCommDemo>打开控制台,然后单击。我< /按钮>');

$(#gmCommDemo)。click(function(){
// ---这下一个值可以来自页面或注入代码的JS
var fetchURL =http://www.google.com/;

// ---标记消息,以防万一有多于一种类型飞行......
var messageTxt = JSON.stringify([fetchURL,fetchURL])

window.postMessage(messageTxt,*);
console.log(Posting message);
});
}

withPages_jQuery(InjectDemoCode);

// ---这段代码侦听正确类型的消息并调用GM_xmlhttpRequest。
window.addEventListener(message,receiveMessage,false);

函数receiveMessage(event){
var messageJSON;
尝试{
messageJSON = JSON.parse(event.data);

catch(zError){
//什么也不做
}
console.log(messageJSON:,messageJSON);

if(!messageJSON)return; // - 消息不适合我们。

if(messageJSON [0] ==fetchURL){
var fetchURL = messageJSON [1];

GM_xmlhttpRequest({
方法:'GET',
url:fetchURL,
onload:function(responseDetails){
//完成所有响应处理HERE ...
console.log(
GM_xmlhttpRequest()response is:\\\

responseDetails.responseText.substring(0,80)+'...'
);
}
});



函数withPages_jQuery(NAMED_FunctionToRun){
// ---使用命名函数进行清晰度和调试...
var funcText = NAMED_FunctionToRun.toString();
var funcName = funcText.replace(/^function\s+(\w+)\s*\((.|\\\
|\r )+$/,$ 1);
var script = document.createElement(script);
script.textContent = funcText +\\\
\\\
;
script.textContent + ='jQuery(document).ready (function(){'+ funcName +'(jQuery);});';
document.body.appendChild(script);
};


I am writing a userscript that is injected into a webpage. The script reads some data from a web-server and I want to send messages to a listening application to react to the data.

For now, all I'm doing is trying to send a string command to my listening application and see if I can read it. My code worked before it was injected, but afterwards I get an "undefined reference error".

I suspect that this has something to do with this "Greasemonkey access violation". However, I have been unable to find a solution that works. I'm developing in Chrome.

Here is the section of code I can't get to work.

GM_xmlhttpRequest({
   method: "POST", 
   url: "http://localhost:7777", 
   data: "testing123",
   headers:  {
         "Content-Type": "application/x-www-form-urlencoded"
             },
   onload: function(response) 
   {
      if (response.responseText.indexOf("TEST") > -1) 
      {
         console.log("Response confirmed..."); 
      }
   }
}); 

I'm pretty new to scripting so maybe I'm missing something obvious. How do I get this to work in injected code?

解决方案

GM_ functions will not work in injected code because injected code runs in the target page's scope. If they did work there, then unscrupulous web-sites could also use the GM_ functions -- to do unspeakable evil.

The solutions, most preferable first:

  1. Don't inject code. Much of the time, it really isn't necessary, and it always complicates things. Only inject code if you absolutely, positively need to use some of the javascript loaded by the target page.

    For libraries like jQuery, you will get better performance using the @require directive (Firefox), or pasting-in the library code or using a custom manifest.json file to include it (Chrome).

    By not injecting code, you:

    1. Keep the ability to easily use GM_ functions
    2. Avoid or reduce the dependency on outside servers to deliver libraries.
    3. Avoid potential side effects and dependencies with/on the page's JS. (You could even use something like NoScript to completely disable the page's JS, while your script still runs.)
    4. Prevent malicious web sites from exploiting your script to gain access to the GM_ functions.

  2. Use the Tampermonkey extension (Chrome). This allows you to avoid script injection by providing better Greasemonkey emulation. You can use the @require directive and a more powerful/risky version of unsafeWindow than Chrome natively provides.

  3. Split your userscript code into injected parts -- which cannot use GM_ functions -- and non-injected parts. Use messaging, polling, and/or a specific DOM node to communicate between the scopes.



If you really must use injected code, here's a sample script that shows how to do it:

// ==UserScript==
// @name        _Fire GM_ function from injected code
// @include     https://stackoverflow.com/*
// @grant       GM_xmlhttpRequest
// ==/UserScript==
/* Warning:  Using @match versus @include can kill the Cross-domain ability of
    GM_xmlhttpRequest!  Bug?
*/

function InjectDemoCode ($) {
    $("body").prepend ('<button id="gmCommDemo">Open the console and then click me.</button>');

    $("#gmCommDemo").click ( function () {
        //--- This next value could be from the page's or the injected-code's JS.
        var fetchURL    = "http://www.google.com/";

        //--- Tag the message, in case there's more than one type flying about...
        var messageTxt  = JSON.stringify (["fetchURL", fetchURL])

        window.postMessage (messageTxt, "*");
        console.log ("Posting message");
    } );
}

withPages_jQuery (InjectDemoCode);

//--- This code listens for the right kind of message and calls GM_xmlhttpRequest.
window.addEventListener ("message", receiveMessage, false);

function receiveMessage (event) {
    var messageJSON;
    try {
        messageJSON     = JSON.parse (event.data);
    }
    catch (zError) {
        // Do nothing
    }
    console.log ("messageJSON:", messageJSON);

    if ( ! messageJSON) return; //-- Message is not for us.

    if (messageJSON[0] == "fetchURL") {
        var fetchURL    = messageJSON[1];

        GM_xmlhttpRequest ( {
            method:     'GET',
            url:        fetchURL,
            onload:     function (responseDetails) {
                            // DO ALL RESPONSE PROCESSING HERE...
                            console.log (
                                "GM_xmlhttpRequest() response is:\n",
                                responseDetails.responseText.substring (0, 80) + '...'
                            );
                        }
        } );
    }
}

function withPages_jQuery (NAMED_FunctionToRun) {
    //--- Use named functions for clarity and debugging...
    var funcText        = NAMED_FunctionToRun.toString ();
    var funcName        = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "$1");
    var script          = document.createElement ("script");
    script.textContent  = funcText + "\n\n";
    script.textContent += 'jQuery(document).ready( function () {' + funcName + '(jQuery);} );';
    document.body.appendChild (script);
};

这篇关于如何在注入代码中使用GM_xmlhttpRequest?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆