(五)JavaScript关于浏览器--ajax

(五)JavaScript关于浏览器--ajax

五、ajax

Asynchronous JavaScript and XML:就是用JavaScript执行异步网络请求。

如一个form表单的提交,一旦“submit”后,表单提交(点击按钮一般是先触发onsubmit,在提交到action),就会跳转到action页面;这是因为在web中一次HTTP请求对应一个页面。

而如果用JavaScript发送这个请求,接收到数据后,再用JavaScript更新页面,用户就感觉自己仍然停留在原来的页面,但是数据却可以不断地更新。

AJAX主要依靠XMLHttpRequest对象:点击打开链接


默认情况下,JavaScript在发送AJAX请求时,URL的域名必须和当前页面完全一致。完全一致的意思是,域名要相同( www.example.comexample.com不同),协议要相同( httphttps不同),端口号要相同(默认是 :80端口,它和 :8080就不同)。


跨域原因由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的内容).

JavaScript请求跨域的两种方式,方法:

1.JSONP (JSON with Padding),它允许在服务器端集成Scripttags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。但是,它有个限制,只能用GET请求,并且要求返回JavaScript。这种方式跨域实际上是利用了浏览器允许跨域引用JavaScript资源:

<scriptsrc="http://example.com/abc.js"></script>

通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。(找了一段代码)

跨域访问:http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction

<?php
header('Content-type: application/json');
//获取回调函数名 注册回调函数
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json数据
$json_data = '["customername1","customername2"]';
//输出jsonp格式的数据
echo $jsoncallback . "(" . $json_data . ")";
?>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
    <div id="divCustomers"></div>
    <script type="text/javascript">
function callbackFunction(result, methodName)
        {
            var html = '<ul>';
            for(var i = 0; i < result.length; i++)
            {
                html += '<li>' + result[i] + '</li>';
            }
            html += '</ul>';
            document.getElementById('divCustomers').innerHTML = html;
        }
</script>
<script type="text/javascript" src="http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=callbackFunction"></script>
</body>
</html> 

2.CORS 允许一个域上的网络应用向另一个域提交跨域AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。

http://www.test1.com打算从http://www.test2.com 请求数据。如果我们直接使用 AJAX 来请求将会失败;利用 CORS,http://www.test2.com 只需添加一个标头,就可以允许来自 http://www.test1.com 的请求:(*为允许任何域请求,可以改为http://www.test1.com)

// 所以如果在服务端代码中设置:这样的话任何域名都可以请求你的服务器了
header(“Access-Control-Allow-Origin:*”);

或者在要请求的域的服务器web.xml中配置,该过滤器可以通过添加必需的访问控制请求头Access-Control-*对象来进行跨域。同时还可以对一些请求进行拦截。如果请求是无效的,或者是不被允许的,该请求被拒绝或者禁止。

<filter>
        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
        <init-param>
            <param-name>cors.allowed.origins</param-name>
            <param-value>
                http://localhost:8080,
                https://localhost:8443
            </param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.methods</param-name>
            <param-value>
                GET,POST,HEAD,OPTIONS,PUT
            </param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.headers</param-name>
            <param-value>
                Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Access-Control-Allow-Origin
            </param-value>
        </init-param>
        <init-param>
            <param-name>cors.exposed.headers</param-name>
            <param-value>
                Access-Control-Allow-Origin,Access-Control-Allow-Credentials
            </param-value>
        </init-param>
        <init-param>
            <param-name>cors.support.credentials</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.preflight.maxage</param-name>
            <param-value>10</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/wxrefund/*</url-pattern>
    </filter-mapping>

浏览器拒绝HTTP请求的跨域,CORS的背后基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求响应是应该成功还是应该失败。

浏览器直接发出CORS请求(在头信息中增加一个Origin字段,说明:本次请求来自哪个源)

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin

Access-Control-Allow-Origin,该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

Access-Control-Allow-Credentials,该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

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

示例:

客服端(就是JavaScript中)

function getHello() {
            var xhr = new XMLHttpRequest();
            xhr.open("post", "http://b.example.com/Test.ashx", true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");    
            // 声明请求源
            xhr.setRequestHeader("Origin", "http://a.example.com");
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var responseText = xhr.responseText;
                    console.info(responseText);
                }
            }
            xhr.send();
        }

服务器端:

public class Test : IHttpHandler{
        public void ProcessRequest(HttpContext context){
            context.Response.ContentType = "text/plain";
            // 声明接受所有域的请求
            context.Response.AddHeader("Access-Control-Allow-Origin", "*");
            context.Response.Write("Hello World");
        }
        public bool IsReusable{
            get
            {
                return false;
            }
        }
    }

有点思路整理下;

我在浏览器(JavaScript)上向一个服务器发送请求,浏览器会拒绝这个请求,怎么解决呢?

首先,JavaScript发送请求时添加头xhr.setRequestHeader("Origin","http://a.example.com");这样浏览器就不会拒绝它;

而服务器回的报头Access-Control-Allow-Origin:*就能与JavaScript相通。



猜你喜欢

转载自blog.csdn.net/qq_35418250/article/details/77895622