• 遭遇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 属性设置。




  • 相关阅读:
    基于@vueuse/core + @vue/compositionapi 实现多行元素展开/折叠功能
    httpserver当作服务器启动项目
    深入浅析JSON.parse()、JSON.stringify()和eval()的作用详解
    es6的新语法fetch
    php shell_exec() 调用ffmpeg遇到的问题
    phpcurl 遇到 cloudflare防御
    Visual Studio Code离线安装扩展失败 Corrupt ZIP: end of central directory record signature not found
    网络常用子网掩码划分表
    [docker pull nginx] Error response from daemon: Get "https://registry1.docker.io/v2/": dial tcp: lookup registry1.docker.io: no such host
    长度延展攻击
  • 原文地址:https://www.cnblogs.com/cs_net/p/2322137.html
Copyright © 2020-2023  润新知