同源策略
ajax的出现虽然促进了web的发展,但是也带来了安全性方面的问题。
比如我们可以通过xxs将脚本注入到目标网页中,实时的向我们的服务器发送用户的所有操作。
为了保证前端的安全性,推出了同源策略,即无法通过xhr向其他服务器发送信息。
下面是node服务端代码,作为一个简单的http静态服务器。
- var http = require("http");
- var url = require('url');
- var path = require('path');
- var fs = require('fs');
-
- var MIME = {
-
- "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"
-
- }
-
- var routeHandle = {};
-
- function route(handle,pathname,request,response) {
- // path.extname(relPath) 获取文件后缀名
- if (path.extname(pathname)) {
- // 静态文件 处理
- doStaticFile(pathname,response);
- }
- else {
- // action 处理
- response.writeHead(200,{ 'Content-Type': 'text/plain;charset=utf-8' });
- response.write("成功");
- response.end();
- }
- }
-
- function doStaticFile(relPath,response) {
- relPath = relPath.indexOf('/') == 0 ? relPath.replace('/','') : relPath;
- fs.exists(relPath,function (exists) {
- if (!exists) {
- response.writeHead(404,{ 'Content-Type': 'text/plain;;charset=utf-8' });
-
- response.write("请求的路径不存在:" + relPath);
-
- response.end();
- } else {
- fs.readFile(relPath,'binary',function (err,file) {
- if (err) {
- // 服务器异常
- response.writeHead(500,{ 'Content-Type': 'text/plain;;charset=utf-8' });
-
- response.end();
- } else {
- // 返回静态文件
- var suffix = path.extname(relPath);
-
- // 由于extname返回值包含”.”,所以通过slice方法来剔除掉”.”
- var mime = MIME[suffix.slice(1)] || 'text/plain';
-
- response.writeHead(200,{ 'Content-Type': mime });
-
- response.write(file,"binary");
-
- response.end();
- }
- })
- }
- })
-
- }
-
- http.createServer(function (request,response) {
-
- var pathname = url.parse(request.url).pathname;
-
- route(routeHandle,response);
-
- }).listen(10000,'127.0.0.1');
下面是客户端的测试代码
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <Meta charset="UTF-8">
- <title>Document</title>
- </head>
- <body>
- <script> var orderHost = "http://127.0.0.1:10000"; var request = new XMLHttpRequest(); request.open("get",orderHost+"/test",true); request.onreadystatechange = function(){ if(request.readyState == 4){ console.log(request); } } request.send(null); </script>
- </body>
- </html>
浏览器通过 http://127.0.0.1:10000/index.html
访问
访问成功,这次试下 http://localhost:10000/index.html
非常好,成功触发同源策略。
jsonP跨域
同源策略限制的是xhr请求,对标签(script、img、link等)并没有限制。
jsonP跨域通过script标签的src来实现跨域。
利用script标签的自执行特点,在服务端生成js代码,调用客户端传来的回调函数,将数据传入进去。
- var querystring = require('querystring');
- ...
-
- function route(handle,{ 'Content-Type': 'text/javascript;charset=utf-8' });
- var query = url.parse(request.url).query;
- var param = querystring.parse(query); // 序列化成对象
- var data = {
- say: '跨域成功'
- }
- // 回调方法
- response.write(
- '(function(){'
- + param['callback'] + '(' + JSON.stringify(data) + ')'
- + '})()'
- );
- response.end();
- }
- }
客户端
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <Meta charset="UTF-8">
- <title>Document</title>
- </head>
-
- <body>
- <script> var orderHost = "http://127.0.0.1:10000"; var script = document.createElement("script"); script.src = orderHost+"/test?callback=testFn"; function testFn(data){ console.log(data.say); } document.getElementsByTagName("head")[0].appendChild(script); </script>
- </body>
-
- </html>
最终结果,成功实现跨域。