Rocho.J

人脑是不可靠的, 随时记录感悟并且经常重复!

 

遭遇Javascript跨站访问的问题(400错误), 还遇到个大写I小写i的错误, 调得我都吐了

功能已经做完后, 发现有JS跨站访问的问题. 自己写了段JS请求转发器来解决这个问题.

 

情况是这样的:

请求Web服务器返回页面, 根据页面选择的条件绑定JS脚本在按钮上, 点击按钮之后, 需要发请求给Jenkins(跟Web服务器不在一起), 并解析Jenkins的返回结果, 显示在Web页面上.  典型的JS跨站, 安全性考虑:  客户端从Web服务器上拿到脚本, 该脚本只允许访问Web服务器上的资源, 如果JS中有访问另外一台服务器的代码, 则禁止访问, 返回400错误.

 

解决方法:

把JS脚本中请求Jenkins的地址(非Web服务器资源), 通通替换成Web服务器上的一个一般处理程序(JS跨站请求转发器), 在这个一般处理程序中, 将请求地址换成Jenkins的请求地址, 并将获得的返回结果回送给JS. 这样就完成了JS的跨站请求访问.

 

实例代码:

说明: 1. 只贴需要用的代码, 程序无法运行.

       2.  年前赶时间, 要完成功能, 没有很好的考虑封装的问题, 代码臃肿, 将就看.

 

后台CS关键代码:

View Code
//其中的"/common/XSSTransferHandler.ashx?url="就是负责转发跨站请求的一般处理程序, url请求参数用来分隔原始请求的请求参数
this.btnStructure.Attributes.Add("onclick", string.Format("return preStructure('{0}');", "http://" + this.Request.Url.Authority + "/common/XSSTransferHandler.ashx?url="));

 

前台JS关键代码(JS不熟写的尤其乱):  这里有个东西解释下, 大部分都是异步的JS请求, 所以入口函数是: preStructure, 在该函数里构造了一个二维数组用来记录异步JS请求时各种状态信息, 如: 闭包函数的ID, 方便请求成功时终止闭包.

View Code
//###Start.自动编译###==>JS异步请求给定的URL,获得返回结果显示在页面上
var structureUrl;
var structureFlagTable; //任务名称|标志位, 其中:0初始状态(即编译中), 1表示编译失败, 2表示编译成功, 3表示打包中, 4表示打包失败, 5表示打包成功
function ajaxMethod(url, reqMethod, async, dealResultFunction, structureId) {
var xhr;
if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
throw new Error("Ajax is not supported by this browser");
}

//处理返回结果的方法
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//将结果显示在弹出的新DIV上;
if(dealResultFunction != null)
dealResultFunction(xhr.responseText);
}
}
}
//发送构建请求
xhr.open(reqMethod, url, async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (structureId != -1)
xhr.setRequestHeader("n", structureId.toString());
xhr.send(null);
}

function structure(url) {
var startReqUrl = url + "/build?delay=0sec";
var getRequestUrl = url + "/buildHistory/ajax";

window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>启动编译任务< " + url.substring(url.lastIndexOf("/")+1) + " >...</font>";

//同步方式获取最近更新构建ID
var xhr;
if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
else if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
throw new Error("Ajax is not supported by this browser");
}
xhr.open("get", url, false);
xhr.send(null);

//处理结果
var lastId = getLastStuctureId(xhr.responseText);
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>编译任务开始< " + url.substring(url.lastIndexOf("/")+1) + " >...</font>";

//异步启动构建任务
ajaxMethod(startReqUrl, "get", true, null, -1);
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>编译任务< " + url.substring(url.lastIndexOf("/")+1) + " >正在执行...</font>";
//异步处理返回结果
function inner() {
ajaxMethod(getRequestUrl, "post", true, showStructureResult, parseInt(lastId) + 1);
}
//setStructureTableValue(url.substring(url.lastIndexOf("/")+1), 3, setInterval(inner, 5000));
setStructureTableValue(url.substring(url.lastIndexOf("=") + 1), 3, setInterval(inner, 5000));
}


//更具context的内容返回最近构建Id
function getLastStuctureId(resContext) {
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>编译任务开始...</font>";
var regPattern = /<\s*a\s*href=\"lastBuild\/\">Last\s+build\(\#([\d]+)\),[\W\w]+?<\s*\/\s*a\s*>/gi;
var result = regPattern.exec(resContext);
return (result == null || result[1] == null) ? "0" : result[1]; //返回最近Build的BuildID
}

//处理返回结果, 并显示在页面上
function showStructureResult(responseContext) {
var divShow = window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResult");
var packUrlPattern = /<a\s+class=\"tip"\s+href=\"\/job\/(.*?)\/.*?([\d]{4}-[\d]{1,2}-[\d]{1,2}\s{1}[\d]{1,2}\:[\d]{1,2}:[\d]{1,2}).*?<\/a>/;
var regPat1 = /src=\"/g;
var regPat2 = /href=\"/g;
var removeBar = /<tr\s+class=\"transitive\">[\s\S]*<\/tr><\/table>/;
var structureName = (packUrlPattern.exec(responseContext) != null && packUrlPattern.exec(responseContext)[1] != null) ? packUrlPattern.exec(responseContext)[1] : "";
var timePath = stringTime(packUrlPattern.exec(responseContext)[2]);
divShow.innerHTML = responseContext.replace(removeBar, "</table>").replace(regPat1, "src=\"http://192.168.199.61:8080").replace(regPat2, "href=\"http://192.168.199.61:8080");

if (divShow.innerHTML.indexOf("Success") != -1) {
window.clearInterval(getStructureTableValue(structureName,3));
setStructureTableValue(structureName, 2, structureName + "_" + timePath + ".tar.gz"); //暂存tar包的名称
setStructureTableValue(structureName, 1, 2);
//启动打包任务
packageTar(structureUrl + structureName);
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>&lt; " + structureName + " &gt;编译成功, 正在打包...</font>";
}
else if (divShow.innerHTML.indexOf("Failed") != -1) {
window.clearInterval(getStructureTableValue(structureName, 3));
window.clearInterval(flagTableID);
setStructureTableValue(structureName, 1, 1);
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='red'>&lt; " + structureName + " &gt;编译失败, 任务终止...</font>";
}
else {
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>编译任务&lt; " + structureName + " &gt;正在执行...</font>";
}
}

//选择多个应用时, 在隐藏域中会生成构建任务列表, 根据构建任务列表执行多个构建任务
var flagTableID;
function preStructure(url) {
//判断是否勾选环境
var choseEviron = window.document.getElementById("ctl00_ContentPlaceHolder1_chkEnvironment").childNodes;
var isChose = false;
for (var v = 0; v < choseEviron.length; v += 2) {
if (choseEviron[v].tagName == "INPUT" && choseEviron[v].checked == true) {
isChose = true;
break;
}
}
if (isChose) {
window.document.getElementById("ctl00_ContentPlaceHolder1_chkEnvironment").style.backgroundColor = "#FFFFFF";
}
else {
window.document.getElementById("ctl00_ContentPlaceHolder1_chkEnvironment").style.backgroundColor = "#FEB8B8";
return false;
}

structureFlagTable = []; //清空JS的数组
structureUrl = url;
var hidValue = window.document.getElementById("ctl00$ContentPlaceHolder1$hiddenFldStructureList").value.split(",");
var errorCount;
var successCount;
//初始化构建任务标识表
structureFlagTable = new Array(hidValue.length);
for (var v = 0; v < hidValue.length; v++) {
structureFlagTable[v] = [hidValue[v], 0, "",0,0];
}

function inner() {
errorCount = 0;
successCount = 0;
for (var v = 0; v < structureFlagTable.length; v++) {
if (structureFlagTable[v][1] == 1 || structureFlagTable[v][1] == 4) {
errorCount++;
break;
}
if (structureFlagTable[v][1] == 5) {
successCount++;
}
}
showCompileAndPackageResult();
if (errorCount > 0 || successCount == structureFlagTable.length) {
window.clearInterval(flagTableID);
if (successCount == structureFlagTable.length) {
var resultShow = window.document.getElementById("ctl00$ContentPlaceHolder1$txtCode");
var tagUrl = "";

//通知执行多个MakeTar
var testEnvironment = {
"厂商测试环境SiteA": "Tar_ComTestA",
"厂商测试环境SiteB": "Tar_ComTestB",
"功能测试环境SiteA": "Tar_FunTestA",
"功能测试环境SiteB": "Tar_FunTestB",
"功能测试环境SiteC": "Tar_FunTestC"
};
var tempUrl = "";
var tempUrlBase = "";

choseEviron = window.document.getElementById("ctl00_ContentPlaceHolder1_chkEnvironment").childNodes;
for (var v = 0; v < structureFlagTable.length; v++) {
tagUrl += structureFlagTable[v][2] + "\r\n";
tempUrlBase = structureUrl + structureFlagTable[v][0] + "/batchTasks/task/Tar_CompilerMachine/execute";
for (var u = 0; u < choseEviron.length; u += 2) {
if (choseEviron[u].tagName == "INPUT" && choseEviron[u].checked == true) {
tempUrl = tempUrlBase.replace("Tar_CompilerMachine", testEnvironment[choseEviron[u + 1].innerText]);
ajaxMethod(tempUrl, "get", true, null, -1);
}
}
resultShow.value = tagUrl;
}
//允许点击提交
window.document.getElementById("ctl00_ContentPlaceHolder1_btnSubmit").disabled = false;
alert("所有构建任务均成功出包!");
}
}
}
//启动构建任务
for (var v = 0; v < structureFlagTable.length; v++) {
structure(structureUrl + structureFlagTable[v][0]);
}
flagTableID = setInterval(inner, 5000);
}

//显示编译结果
function showCompileAndPackageResult() {
var resultShow = window.document.getElementById("ctl00$ContentPlaceHolder1$txtCode");
var resultText = "";
for (var v = 0; v < structureFlagTable.length; v++) {
switch (structureFlagTable[v][1]) {
case 0:
resultText += structureFlagTable[v][0] + ": 正在编译...\r\n";
break;
case 1:
resultText += structureFlagTable[v][0] + ": 编译失败!\r\n";
break;
case 2:
resultText += structureFlagTable[v][0] + ": 编译成功!\r\n";
break;
case 3:
resultText += structureFlagTable[v][0] + ": 正在打包...!\r\n";
break;
case 4:
resultText += structureFlagTable[v][0] + ": 打包失败!\r\n";
break;
case 5:
resultText += structureFlagTable[v][0] + ": 打包成功!\r\n";
break;
default:
resultText += "未知异常\r\n";
}
}
resultShow.value = resultText;
}

//设置构建任务表示表的值, 注意字符串后便可能还有换行符
function setStructureTableValue(key, colIndex, value) {
for (var v = 0; v < structureFlagTable.length; v++) {
if (key.toLowerCase() == structureFlagTable[v][0].toLowerCase()) {
structureFlagTable[v][colIndex] = value;
}
}
}

//获取构建任务标示表的值
function getStructureTableValue(key, colIndex) {
for (var v = 0; v < structureFlagTable.length; v++) {
if (key.toLowerCase() == structureFlagTable[v][0].toLowerCase()) {
return structureFlagTable[v][colIndex];
}
}
}
//###End.###==>

//###Start.自动打包###
var packageId;
function packageTar(url) {
var startBuildUrl = url + "/batchTasks/task/Tar_CompilerMachine/execute";
var getBuildUrl = url + "/batchTasks/task/Tar_CompilerMachine/";
//var structureName = url.substring(url.lastIndexOf("/")+1);
var structureName = url.substring(url.lastIndexOf("=") + 1);
setStructureTableValue(structureName, 1, 3);

//同步启动构建任务
ajaxMethod(startBuildUrl, "get", true, null, -1);

//异步处理返回结果
function inner() {
ajaxMethod(getBuildUrl, "post", true, showBuildResult, -1);
}
setStructureTableValue(structureName, 4, setInterval(inner, 5000));
}

//处理返回结果, 并显示在页面上
function showBuildResult(responseContext) {
var divShow = window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResult");
var regPattern = /<tr\s+class=\"build-row\s+no-wrap\s+\">[\s\S]*?<\/tr>/;
var struNamePattern = /<a\s+href=\"\/job\/[\s\S]*?\/\">([\s\S]*?)<\/a>/;
var regPat1 = /src=\"/g;
var regPat2 = /href=\"/g;
var result = (regPattern.exec(responseContext) != null && regPattern.exec(responseContext)[0] != null) ? (regPattern.exec(responseContext)[0]).replace(regPat1, "src=\"http://192.168.199.61:8080").replace(regPat2, "href=\"http://192.168.199.61:8080") : "";
var structureName = (struNamePattern.exec(responseContext) != null && struNamePattern.exec(responseContext)[1] != null) ? struNamePattern.exec(responseContext)[1] : "";
divShow.innerHTML = "<table>" + result + "</table>";
if (result.indexOf("Success") != -1) {
window.clearInterval(getStructureTableValue(structureName, 4));
var tarBagUrl = "http://192.168.199.61:9082/"; //将出包后的源码默认URL路径
setStructureTableValue(structureName, 2, tarBagUrl + getStructureTableValue(structureName, 2));
setStructureTableValue(structureName, 1, 5);
if (getStructureTableValue(structureName, 2).indexOf(tarBagUrl) != -1) {
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'> " + structureName + " 成功出包!</font>";
}
}
else if (divShow.innerHTML.indexOf("Failed") != -1) {
window.clearInterval(getStructureTableValue(structureName, 4));
window.clearInterval(flagTableID);
setStructureTableValue(structureName, 1, 4);
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='red'>出包失败......</font>";
}
else {
window.document.getElementById("ctl00_ContentPlaceHolder1_divBuildResultStatus").innerHTML = "<font color='green'>出包中...</font>";
}
}

function stringTime(timeString) {
if (timeString != "") {
var dateTime = timeString.split(' ');
var tempDate = ("00" + dateTime[0]).replace(/\-/g, "-00").split("-");
var tempTime = ("00" + dateTime[1]).replace(/\:/g, ":00").split(":");
var date = "";
var time = "";
for (var v = 0; v < tempDate.length; v++) {
if (tempDate[v].length != 6) {
date += tempDate[v].substring(tempDate[v].length - 2, 4) + "-";
}
else {
date += tempDate[v].substring(tempDate[v].length - 4, 6) + "-";
}
}
date = date.substring(0, date.length - 1);
for (var v = 0; v < tempTime.length; v++) {
time += tempTime[v].substring(tempTime[v].length - 2, 4) + "-"
}
time = time.substring(0, time.length - 1);
return date + "_" + time;
}
}
//###End.###==>



  JavaScript跨站请求转发器, 一般处理程序

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;

using System.Net;
using System.IO;
using System.Text;

namespace WebSite.Common
{
    /// <summary>
    /// JS跨站转发器, 用来解决JavaScript无法跨站传输的问题
    /// </summary>
    public class XSSTransferHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {
        private static readonly string StructureUrl = ConfigurationManager.AppSettings["StructureUrl"];

        public void ProcessRequest(HttpContext context)
        {
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.ContentType = "text/html";
            if ((context.Session["_userRoles"] as List<string>).Count != 0)
            {
                if ((context.Session["_userRoles"] as List<string>).Contains("开发负责人") || (context.Session["_userRoles"] as List<string>).Contains("管理员"))
                {
                    if (!string.IsNullOrEmpty(context.Request.Url.PathAndQuery) && context.Request.Url.PathAndQuery.StartsWith("/common/XSSTransferHandler.ashx?url="))
                    {
                        string newUrl = context.Request.Url.AbsoluteUri.Replace("http://" + context.Request.Url.Authority + "/common/XSSTransferHandler.ashx?url=", StructureUrl);
                        HttpWebRequest hwrRequest = HttpWebRequest.Create(newUrl) as HttpWebRequest;
                        //添加请求头, 其中Accept、Content-Length、Content-Type、User-Agent只能通过如下方式设置
 hwrRequest.ContentType = "application/x-www-form-urlencoded";   //表头的格式必须要写,否则请求响应的页面得不到要传递的值

                        foreach (string str in context.Request.Headers.Keys)
                        {
                            switch (str)
                            {
                                case "Accept":
                                    hwrRequest.Accept = context.Request.Headers["Accept"];
                                    break;
                                case "Connection":
                                    break;
                                case "Content-Length":
                                    hwrRequest.ContentLength = int.Parse(context.Request.Headers["Content-Length"]);
                                    break;
                                case "Content-Type":
                                    hwrRequest.ContentType = context.Request.Headers["Content-Type"];
                                    break;
                                case "Expect":
                                    break;
                                case "Date":
                                    break;
                                case "Host":
                                    break;
                                case "If-Modified-Since":
                                    break;
                                case "Range":
                                    break;
                                case "Referer":
                                    break;
                                case "Transfer-Encoding":
                                    break;
                                case "User-Agent":
                                    hwrRequest.UserAgent = context.Request.Headers["User-Agent"];
                                    break;
                                default:
                                    hwrRequest.Headers.Add(str, context.Request.Headers[str]);
                                    break;
                            }
                        }

                        switch (context.Request.HttpMethod)
                        {
                            case "GET":
                                hwrRequest.Method = "GET";
                                break;
                            case "POST":
                                hwrRequest.Method = "POST";
                                //hwrRequest.ContentType = "application/x-www-form-urlencoded";   //表头的格式必须要写,否则请求响应的页面得不到要传递的值
                                string postBodyStr = "";    //Post请求包体内容
                                //获取POST请求包体
                                using (Stream stream = context.Request.InputStream)
                                using (StreamReader sReader = new StreamReader(stream, Encoding.UTF8))
                                {
                                    try
                                    {
                                        postBodyStr = sReader.ReadToEnd();  //读取请求参数的包体内容
                                        if (!string.IsNullOrEmpty(postBodyStr))
                                        {
                                            byte[] postBodyBytes = Encoding.Default.GetBytes(postBodyStr);//传递的值
                                            hwrRequest.ContentLength = postBodyBytes.Length;
                                            //把传递的值写到流中
                                            using (System.IO.Stream newStream = hwrRequest.GetRequestStream())
                                            {
                                                try
                                                {
                                                    newStream.Write(postBodyBytes, 0, postBodyBytes.Length);
                                                }
                                                catch (Exception ex)
                                                {
                                                    throw ex;
                                                }
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        throw ex;
                                    }
                                }
                                break;
                            default:
                                throw new HttpException("未支持的请求方式!");
                        }

                        //处理返回信息
                        using (HttpWebResponse hwrResponse = hwrRequest.GetResponse() as HttpWebResponse)
                        using (Stream stream = hwrResponse.GetResponseStream())
                        using (StreamReader sReader = new StreamReader(stream, Encoding.UTF8))
                        {
                            try
                            {
                                string responseHTML = sReader.ReadToEnd();
                                context.Response.Write(responseHTML);
                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                        }
                    }
                }
                else
                {
                    context.Response.Redirect("~/Default.aspx");
                }
            }
            else
            {
                context.Response.Redirect("~/Default.aspx");
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

 

 

 

需要着重说明的事项:

1. 尤其要看跨站安全性部分的写法, 平时注意一下吧. 我这个纯内网环境, 内部各种服务器, 业务复杂一下, 安全性要求不高.

View Code
跨域 XMLHttpRequest 请求
普通网页能够使用XMLHttpRequest对象发送或者接受服务器数据, 但是它们受限于同源策略. 扩展可以不受该限制. 任何扩展只要它先获取了跨域请求许可,就可以进行跨域请求。

注意:页面内容脚本不能直接发起跨域请求. 然而, 任何一个页面内容脚本都可以发送消息给父扩展,请求父扩展发起一次跨域请求。关于使用这一技术的例子,请参照contentscript_xhr example.

扩展所属域
每个正在运行的扩展都存在于自己独立的安全域里. 当没有获取其他权限时,扩展能够使用XMLHttpRequest获取来自安装该扩展的域的资源. 例如, 假设有一个扩展包含一个叫config.json的JSON配置文件,该文件位于config_resources?目录, 那么该扩展能够使用下面这段代码获取文件内容:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange; // Implemented elsewhere.
xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true);
xhr.send();
如果某个扩展希望访问自己所属域以外的资源,比如说来自http://www.google.com的资源(假设该扩展不是来自www.google.com), 浏览器不会允许这样的请求,除非该扩展获得了相应的跨域请求允许。

获取跨域请求允许
通过添加域名或者域名匹配到manifest文件的permissions段, 该扩展就拥有了访问除了自己所属域以外的其他域的访问权限.

{
"name": "My extension",
...
"permissions": [
"http://www.google.com/"
],
...
}跨域允许设置可以使用完整域名, 例如:

"http://www.google.com/"
"http://www.gmail.com/"
或者使用模式匹配, 例如:

"http://*.google.com/"
"http://*/"
模式匹配"http://*/" 表示可以发起到所有域的HTTP请求. 注意在这里, 模式匹配有点像内容脚本匹配, 但是这里的任何域名后的路径信息都被忽略

这里还需要注意访问权限是根据访问协议(匹配模式里的http或者https或者其他协议名)及域名来授予的. 例如某个扩展希望同时基于https和http协议访问某个域或者某些域, 那么它必须分别获取基于这两种协议的访问允许(类似下面这样的声明):

"permissions": [
"http://www.google.com/",
"https://www.google.com/"
]
安全性考虑
每当使用通过XMLHttpRequest获取的资源时, 你编写的背景页需要注意不要成为跨域脚本的牺牲品. 特别注意避免使用像下面这样的危险API:

background.html
===============
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// 警告! 这里有可能执行了一段恶意脚本!
var resp = eval("(" + xhr.responseText + ")");
...
}
}
xhr.send();

background.html
===============
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// 警告! 这样处理有可能被注入恶意脚本!
document.getElementById("resp").innerHTML = xhr.responseText;
...
}
}
xhr.send();实际上我们应该首选不会执行脚本的安全API:

background.html
===============
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// JSON解析器不会执行攻击者设计的脚本.
var resp = JSON.parse(xhr.responseText);
}
}
xhr.send();

background.html
===============
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// innerText不会给攻击者注入HTML元素的机会.
document.getElementById("resp").innerText = xhr.responseText;
}
}
xhr.send();另外在使用通过协议HTTP获取的资源时要特别小心. 如果你开发的扩展被应用在恶意网络环境中,网络攻击者(又叫 "中间人攻击") 可能篡改服务器响应内容从而可能攻击你编写的扩展. 事实上,你应该尽可能地首选使用HTTPS协议

 

 

第二个要注意的地方: 在JS跨站请求转发器的代码里, 需要构造HttpWebRequest请求, 构造请求时, 下述集中请求参数必须通过Request的属性来设置, 不能用Add和Set.

下面列出 Headers中不能add或者Set的名字 及解决办

Accept Accept 属性设置。
Connection Connection 属性和 KeepAlive 属性设置。
Content-Length ContentLength 属性设置。
Content-Type ContentType 属性设置。
Expect Expect 属性设置。
Date 由系统设置为当前日期。
Host 由系统设置为当前主机信息。
If-Modified-Since IfModifiedSince 属性设置。
Range AddRange 方法设置。
Referer Referer 属性设置。
Transfer-Encoding TransferEncoding 属性设置(SendChunked 属性必须为 true)。
User-Agent UserAgent 属性设置。




posted on 2012-01-13 23:51  RJ  阅读(2203)  评论(1编辑  收藏  举报

导航