js跨域的几种解决办法

js跨域

    • jsonp 跨域
    • Cors 跨域
    • node配置node-http-proxy 跨域

jsonp 跨域

用原生js实现:

//简单实现jsonp
function jsonpCallback(result) {
    //alert(result);  
    for (var i in result) {
        console.log(i + ":" + result[i]); //循环输出result的元素  
    }
}
var JSONP = document.createElement("script");
JSONP.type = "text/javascript";
JSONP.src = "http://180.167.10.100/update/index.php?callback=jsonpCallback";
document.getElementsByTagName("head")[0].appendChild(JSONP);


//封装好的jsonp
var jsonp = function (url, data, callback) {
    // 1.将传入的data数据转化为url字符串形式
    // {id:1,name:'zhangsan'} => id=1&name=zhangsan
    var dataString = url.indexof('?') == -1 ? '?' : '&';
    for (var key in data) {
        dataString += key + '=' + data[key] + '&';
    };

    // 2 处理url中的回调函数
    // cbFuncName回调函数的名字 :my_json_cb_名字的前缀 + 随机数(把小数点去掉)
    var cbFuncName = 'my_json_cb_' + Math.random().toString().replace('.', '');
    dataString += 'callback=' + cbFuncName;

    // 3.创建一个script标签并插入到页面中
    var scriptEle = document.createElement('script');
    scriptEle.src = url + dataString;

    // 4.挂载回调函数
    window[cbFuncName] = function (data) {
        callback(data);
        // 处理完回调函数的数据之后,删除jsonp的script标签
        document.body.removeChild(scriptEle);
    }

    // 5.append到页面中
    document.body.appendChild(scriptEle);
}

// 因为jsonp是一个私有函数外部不能调用,所有jsonp函数作文window对象的一个方法,供外部调用
window.$jsonp = jsonp;

用jq实现jsonp

$.ajax({
    type: "get",
    async: false,
    url: "http://test.com/json_data.php",
    dataType: "jsonp",
    jsonp: "callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
    jsonpCallback: "mycall", //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
    success: function (data) {
        console.log(data);
    },
    error: function () {
        alert('fail');
    }
});

Cors 跨域

客户端正常发出ajax请求,只需要服务端配置即可,不同的后台语言写法不同,但是配置项是一样的,需要配置以下几个值。
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

(2)Access-Control-Request-Method
该字段用来列出浏览器的CORS请求会用到哪些HTTP方法

(3)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段。

Access-Control-Allow-Credentials: true

另一方面,开发者必须在AJAX请求中打开withCredentials属性。

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

(4)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers面指定。

//例如

header("Access-Control-Allow-Origin: * ");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE");
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, 
Accept, Connection, User-Agent, Cookie,token');
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true

node配置node-http-proxy 跨域

Node.js配合node-http-proxy解决本地开发ajax跨域问题

  1. npm初始化
npm init
  1. 安装node-http-proxy模块
npm install http-proxy --save-dev
  1. 项目结构
    js跨域的几种解决办法_第1张图片
    html文件直接放在根目录’./’,也可以指定一个网站目录,在proxy.js中可以自定义
  2. proxy.js
    配置HTTP服务器和PROXY转发
var PORT = 8088;
var APIServer = 'https://me.csdn.net'; // 后台服务器地址http://172.16.0.111  http://cochat.cn
var APIPrefix = '/api/'; // 反向代理api前缀
var http = require('http');
var url = require('url');
var fs = require('fs');
var mine = require('./mine').types;
var path = require('path');
var httpProxy = require('http-proxy');

var proxy = httpProxy.createProxyServer({
    target: APIServer,   //接口地址
    proxyTimeout: 5 * 60 * 1000,
    // 下面的设置用于https
    // ssl: {
    //     key: fs.readFileSync('server_decrypt.key', 'utf8'),
    //     cert: fs.readFileSync('server.crt', 'utf8')
    // },
    // secure: false
});

proxy.on('error', function (err, req, res) {
    res.writeHead(500, {
        'content-type': 'text/plain'
    });
    console.log(err);
    res.end('Something went wrong. And we are reporting a custom error message.');
});

var server = http.createServer(function (request, response) {
    var pathname = url.parse(request.url).pathname;
    var query = url.parse(request.url).query;
    //var realPath = path.join("main-pages", pathname); // 指定根目录

    //判断如果是接口访问,则通过proxy转发
    if (pathname.indexOf(APIPrefix) > 0) {
        request.url = '/' + pathname.substr(APIPrefix.length) + (query ? '?' + query : '');
        proxy.web(request, response);
        return;
    }

    if (path.extname(pathname) == "") {
        pathname += "/";
    }
    if (pathname.charAt(pathname.length - 1) == "/") {
        pathname += "index.html";
    }
    console.log(pathname);
    var realPath = path.join("./", pathname);
    console.log(realPath);
    fs.exists(realPath, function (exists) {
        if (!exists) {
            response.writeHead(404, {
                'Content-Type': 'text/plain'
            });

            response.write("This request URL " + pathname + " was not found on this server.");
            response.end();
        } else {
            fs.readFile(realPath, "binary", function (err, file) {
                if (err) {
                    response.writeHead(500, {
                        'Content-Type': 'text/plain'
                    });
                    response.end(err);
                } else {
                    var ext = path.extname(realPath);
                    ext = ext ? ext.slice(1) : 'unknown';
                    var contentType = mine[ext] || "text/plain";
                    response.writeHead(200, {
                        'Content-Type': contentType
                    });
                    response.write(file, "binary");
                    response.end();
                }
            });
        }
    });
});
server.listen(PORT);
console.log("Server runing at port: " + PORT + ".");
  1. mine.js
exports.types = {
  "css": "text/css",
  "gif": "image/gif",
  "html": "text/html",
  "ico": "image/x-icon",
  "jpeg": "image/jpeg",
  "jpg": "image/jpeg",
  "js": "text/javascript",
  "json": "application/json",
  "pdf": "application/pdf",
  "png": "image/png",
  "svg": "image/svg+xml",
  "swf": "application/x-shockwave-flash",
  "tiff": "image/tiff",
  "txt": "text/plain",
  "wav": "audio/x-wav",
  "wma": "audio/x-ms-wma",
  "wmv": "video/x-ms-wmv",
  "xml": "text/xml",
  "woff": "application/x-woff",
  "woff2": "application/x-woff2",
  "tff": "application/x-font-truetype",
  "otf": "application/x-font-opentype",
  "eot": "application/vnd.ms-fontobject"
};

启动nodejs服务
启动cmd,定位到项目目录,运行

node proxy.js

访问:

http://localhost:3000/index.html

可以看到项目中调用的http://localhost:3000/… 都会从http://192.168.10.38:8180/… 获取数据,然后转发到本地。

这样就不存在跨域了。

你可能感兴趣的:(js跨域的几种解决办法)