Lifehack for Same-Origin-Policy; Google Chrome and others

    debuger

    Task:
    - there is a REST server
    - there is a one-page application (HTML / CSS / Javascript) that takes data from the server via XMLHttpRequest
    - you need to develop a new feature.



    When the front-end developer has such a task, there are two options:
    - raise the test server yourself on localhost
    - ask the Back-end to add the “Allow-Control-Allow-Origin: *” header to the server’s response in order to use XMLHttpRequest2

    The first option is time-consuming and not always possible. The second option is also not the best - setting “Allow-Control-Allow-Origin: *” seems to be not safe, and the back-end can do this for a long time.

    And then it seemed to me a seemingly trivial idea- why change the headers on the server if this can be done directly on the client.

    About Fiddler I already tried to write once.

    Solution with Fiddler
    Actually, everything is banal and simple.
    - On the Filters tab, turn on Use filters
    - turn on the “Set response header” and add the desired header “Allow-Control-Allow-Origin: *”
    - turn on the “Set request header” is needed for Chrome; not needed; for chromium, see below for flags in chrome

    Everything!

    I’m afraid that if the article ended on this, the audience wouldn’t have appreciated, and would have messed me up and the post a little less than completely, so the solution for those who don’t want to have anything to do with Fedler and who don’t look for easy ways.

    Among the extensions for Chrome, for some reason I did not come across any that could change the Response headers, although maybe I was looking badly. Therefore, I decided to quickly write my bike. link to the extension and github because it's fashionable and youth

    Chrome extension
    manifest.json
    {
    	"name": "Allow-Control-Allow-Origin: *",
    	"version": "1.0",
    	"manifest_version": 2,
    	"description": "Allow to you request any site with ajax from any source. Add to response - 'Allow-Control-Allow-Origin: *' header",
    	"background": {  // собственно подключили скрипт нашего расширения 
    		"scripts": ["background.js"]
    	},
    	"browser_action": { //добавим кнопку расширения с картинкой и заголовком, "default_popup" мне не нужен
    	"default_icon": "off.gif",
    	"default_title": "Allow-Control-Allow-Origin"
    	},
    	"permissions": [ 
    		"storage",     // для localStorage
    		"webRequest",    //для webRequest API
    		"webRequestBlocking",
    		"*://*/*" //хочу посылать запросы на любой адрес 
    	],
    	"web_accessible_resources": [     //ресурсы расширения - чтобы не писать полный путь к картинке когда мы ее будем менять
    		"on.gif","off.gif"
    	]
    }
    

    In a little more detail:
    - “background” - one , two in brief - for the extension to work when Chrome starts in the background.
    In "permissions": ["*: // * / *"] the addresses of sites where the extension works and where there is access to send an ajax request from the extension are indicated. Alternative to "content_scripts" : [...]
    if you need to embed the script directly on the pages of an open site (useful if you need to use functions and variables declared in the site’s scripts, otherwise the extension works in its scope and the site’s scripts in its own)
    - “browser_action” - Needed to add a button to enable and disable the extension
    alternative to "page_action"
    you cannot use page_action and browser_action at the same time
    - webRequest API and webRequestBlocking - replace request and response headers
    - "web_accessible_resources" - otherwise the path to the image should look like this:
    you need the path:
    background-image: url ("/ sprites.png");
    CSS
    background-image: url ('chrome-extension: //__MSG_@@extension_id__/sprites.png');
    JS
    var url = chrome.extension.getURL ('sprites.png');

    backgound.js
    var requestListener = function(details){
    	var flag = false,
    		rule = {
    			name: "Origin",
    			value: "http://evil.com/"
    		};
    	for (var i = 0; i < details.requestHeaders.length; ++i) {
    		if (details.requestHeaders[i].name === rule.name) {
    			flag = true;
    			details.requestHeaders[i].value = rule.value;
    			break;
    		}
    	}
    	if(!flag) details.requestHeaders.push(rule);
    	return {requestHeaders: details.requestHeaders};
    };
    var responseListener = function(details){
    	var rule = {
    			"name": "Access-Control-Allow-Origin",
    			"value": "*"
    		};
    	details.responseHeaders.push(rule);
    	return {responseHeaders: details.responseHeaders};
    };
    /*On install*/
    chrome.runtime.onInstalled.addListener(function(){
    	localStorage.active = false;
    });
    /*Icon change*/
    chrome.browserAction.onClicked.addListener(function(tab){
    	if(localStorage.active === "true"){
    		localStorage.active = false;
    		chrome.browserAction.setIcon({path: "off.gif"});
    		/*Remove Response Listener*/
    		chrome.webRequest.onHeadersReceived.removeListener(responseListener);
    		chrome.webRequest.onBeforeSendHeaders.removeListener(requestListener);
    	}else{
    		localStorage.active = true;
    		chrome.browserAction.setIcon({path: "on.gif"});
    		/*Add Response Listener*/
    		chrome.webRequest.onHeadersReceived.addListener(responseListener,{
    			urls: [
    				"*://*/*"
    			]
    		},["blocking", "responseHeaders"]);
    		chrome.webRequest.onBeforeSendHeaders.addListener(requestListener,{
    			urls: [
    				"*://*/*"
    			]
    		},["requestHeaders"]);
    	}
    });
    


    More details on the code:
    Callbacks for onHeadersReceived and onBeforeSendHeaders put responseListener and requestListener into separate functions, respectively, so that after switching the plugin on and off the headers would not be changed. We remove the attached handlers

    chrome.runtime.onInstalled - it will be executed once - there you can initialize the default state of the plugin

    chrome.browserAction.onClicked .addListener - when we click on the extension button - we catch the event and simulate turning the plugin on and off

    if (localStorage.active === ““ true ") - for some reason, every time I stumble on this and forget that the keys in localStorage are stored in

    In fact, we do not need onBeforeSendHeaders, but since Chrome does not allow ajax requests to be sent from localhost.
    In the first version of the extension, I did not notice this because when I start chrome I have the flag --allow-file-access-from-files.

    More information about the flags can be read here and here.

    I have these:
    Right-click on the shortcut -> Properties -> Targets
    C: \ Users \ Ololo \ AppData \ Local \ Google \ Chrome \ Application \ chrome.exe --allow-file-access-from-files --remote-debugging-port = 9222 --allow-file-access - allow-cross-origin-auth-prompt

    As for FF - for some reason here, too, I did not find extensions for replacing the response from the server, but again, maybe it was looking poorly. If someone tells you I’ll put in a post.

    PS
    I hope you find the extension or advice useful. For those to whom it seemed trite and not worthy of a habr, I apologize, but to at least one person it was not as obvious as it became useful to me (to me).
    I have doubts about security, in principle, with the extension turned on, you can score on any site on CORS , but we are all honest and we will use this only for development.

    PSS
    Does not apply to the topic of the post, but maybe someone wanted and forgot - yesterday (January 21) the next round of online courses on MongoDB began
    Impressions of the course can be read here . Registration for the course should be available within a couple of weeks (judging by the previous round)

    Also popular now: