为了账号安全,请及时绑定邮箱和手机立即绑定

ajax跨域完全讲解

晓风轻 全栈工程师
难度中级
时长 1小时40分
学习人数
综合评分9.70
116人评价 查看评价
9.8 内容实用
9.6 简洁易懂
9.7 逻辑清晰
  • 总的来说, 跨域问题有3个原因:  浏览器的限制, 跨域, xhr(XMLHttpRequest) 请求; 这三个条件同时满足才会产生跨域安全问题

    1. 浏览器的限制

    发生这个跨域问题不是因为后台不允许前台调用, 真正的原因是浏览器出于安全考虑, 当他发现你的请求是跨域的时候, 会对发送的请求进行校验, 如果校验不通过, 就会报跨域错误. 这个时候可能你的请求已经发送成功并且返回了数据, 但控制台报了一条跨域错误, 说明服务器后台式没有任何限制的,   是浏览器报的错; 说白了就是浏览器多管闲事, 而不是后台不允许

    2. 跨域:发出去的请求不是本域的.  请求里面 协议, 域名, 端口任何一个不一样, 浏览器都会认为是跨域; 比如前台是localhost:8080端口, 请求的是localhost:8081端口 , 虽然域名相同, 但端口不一样, 所以跨域了

    3. 发送的是 XHR(XMLHttpRequest) 请求 (也是最重要的原因); 只要发送的不是XHR请求, 比如jsonp请求, 就算是跨域, 浏览器也不会报跨域问题


    <!--此处有图片-->



    03:38
    看视频
  • 我想说在这里的故事将会是怎么样,但是并不是我们所需要的。

    00:18
    看视频
  • 由控制台可以看到,Console 报了一个错误,这就是跨域访问安全问题

    03:55
    看视频
  • 创建Springboot工程,并编写后台服务代码
    03:39
    看视频
  • nginx实现隐藏跨域: 在下面的a.com.conf文件中配置参数后,在前端代码中把请求http://localhost:8081/test地址改成代理地址/ajaxserver

    nginx反向代理配置:

    <!--此处有图片-->

    <!--此处有图片-->


    支持跨域与隐藏跨域的区别:

    支持跨域:调用的url地址都是绝对地址

    隐藏跨域:调用的url都是本域的,是相对地址,





    04:26
    看视频
  • String 框架解决方案: @CrossOrigin  注解,可以在 Controller 上,也可以在 方法上,还可以进行细节配置。

    属于服务端改动的一种。 


    01:19
    看视频
  • 带自定义头的跨域:

    1. ajax示例代码:

    <!--此处有图片-->

    2. 请求头信息

    <!--此处有图片-->

    3. 再次请求将会报如下错误信息:

    <!--此处有图片-->

    解决办法:

    res.addHeader("Access-Control-Allow-Headers", "Content-Type,x-header1,x-header2");

    这种方式把请求头写死了,不推荐

    4. 支持所有跨域,示例代码:

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        HttpServletRequest req = (HttpServletRequest) request;
    
        HttpServletResponse res = (HttpServletResponse) response;
    
        String origin = req.getHeader("Origin");
    
        //res.addHeader("Access-Control-Allow-Origin", "*");  //允许所有的域跨域
        //res.addHeader("Access-Control-Allow-Methods", "*");  //允许所有的方法跨域
    
        if(!StringUtils.isEmpty(origin)){
            //带cookie的时候,origin必须是全匹配,不能使用*
            res.addHeader("Access-Control-Allow-Origin", origin);   //允许跨域
        }
    
        res.addHeader("Access-Control-Allow-Methods", "*");  //允许跨域的方法
    
        String headers = req.getHeader("Access-Control-Request-Headers");
    
        //支持所有自定义头
        if(!StringUtils.isEmpty(headers)){
            res.addHeader("Access-Control-Allow-Headers", headers);
        }
    
        res.addHeader("Access-Control-Max-Age", "3600");
    
        //enable cookie
        res.addHeader("Access-Control-Allow-Credentials", "true");
    
        chain.doFilter(request, response);
    
    }












































  • 当产生跨域的时候,请求头中会多一个字段,叫做origin,这个字段有当前域的信息。所以在发送带cookie的请求,后台又不知道调用方的域的信息时,可以先取到请求头中origin字段的值再赋值给响应头的access-control-allow-origin字段中。


    带Cookie的跨域: 1. "Access-Control-Allow-Credentials","true" 2. Access-Control-Allow-Origin 不能为* ,必须为【调用方】的域名+端口 3. 发送的Cookie是【被调用方】的cookie

  • 一、http会话session依赖于cookie, sessionid存放在cookie中。

    二、ajax

    1、$.ajax({

        type: "get",

        xhrFields: {

            widthCredentials: true // 发送ajax请求的时候会带上cookie

        }

    })

    2、cookie是加在被调用方。

    <!--此处有图片-->

    服务端就是被调用方,而客户端就是调用方。在浏览器的控制台中通过document.cookie=""  来设置cookie。


    3、读cookie只能读到本域的。

    4、带cookie时,后台代码注意以下2点:

    (1)带cookie的时候,Access-Control-Allow-Origin,必须是全匹配,如http://localhost:8081, 不能是 *,否则报错,如下:

    <!--此处有图片-->


    (2)带cookie进行跨域时,需要设置以下请求头:

    res.addHeader("Access-Control-Allow-Credentials", "true")


    05:33
    看视频
  • 我们知道非简单请求, 每次会发出两次请求, 这会影响性能. HTTP协议增加了个响应头, 可以让我们在服务端设置`Access-Control-Max-Age`来缓存预检请求, 比如说我们可以设置为3600m, 也就是一小时客户端只会在第一次的时候发送两个请求, 接下来一个小时内`OPTIONS`请求就被缓存起来了.

    00:46
    看视频
  • 问题1:浏览器是先执行请求还是先判断跨域?

        浏览器请求-->判断响应中是否有允许跨域-->发现不允许跨域,阻止跨域

        说明:当执行跨域请求时,浏览器会提示当前接口不被允许,这说明浏览器已发出了当前请求,但是它的的响应内容被拦截;如果在Response header中的Access-Control-Allow-Origin设置的允许访问源不包含当前源,则拒绝数据返回给当前源。


    当浏览器要发送跨域请求时,如果请求是复杂请求,浏览器会先发送一个options预检命令即一个options请求,当该请求通过时才会再发送真正的请求。

    该option请求会根据请求的信息去询问服务端支不支持该请求。比如发送的数据是json类型(通过content-type设置)的话,会携带一个请求头Access-Control-Request-Headers: content-type去询问支不支持该数据类型,如果支持,则请求就会通过,并发送真正的请求


    04:54
    看视频
  • 简单请求和非简单请求

    1.简单请求是先请求,浏览器再判断是否是跨域;而非简单请求要先发送一个预检命令,检查通过之后才会真正的把跨域请求发出去

    <!--此处有图片-->

    2.非简单请求常见的是发送json格式的请求,如图contentType为“application/json;charset=utf-8”<!--此处有图片-->

    最后的结果如下,返回了两个请求,一个是OPTIONS,另一个是POST请求,其中的OPTIONS就是一个预检命令,成功了之后才会发送后面的跨域请求

    <!--此处有图片-->

    3.预检命令的缓存。因为这种非简单请求每次都会发送两次请求,其实效率是比较低的,但是如果能缓存预检命令的话,会响应的提高效率

    在服务器中,添加一个响应头信息,告诉浏览器在截下来的一个小时可以缓存信息,就不需要再发送预检命令

    <!--此处有图片-->


    04:13
    看视频
  • 被调用方——Filter解决方案:

    1. 浏览器是先执行后判断

    2. 跨域请求和普通请求的区别:

    跨域请求的请求头中多了一条信息:如下

    origin : http://localhost:8081

    这个值是当前请求的域名信息,如果 浏览器发现当前请求是跨域的时候,它就会在当前请求头中添加一个当前域的信息的字段;然后在请求返回的时候,它会检查响应头里面有没有允许跨域的信息存在,如果没有,它就会报错。


    01:34
    看视频
  • 被调用方解决——支持跨域

    01:14
    看视频

举报

0/150
提交
取消
课程须知
需要具备基本的前后台开发技术
老师告诉你能学到什么?
AJAX跨域产生的原因和解决思路 系统的基本部署架构和跨域的关系 http服务器nginx和apache的重要作用和跨域的2种解决思路 jsonp的工作机制和优缺点 前台测试框架Jasmine的使用

微信扫码,参与3人拼团

意见反馈 帮助中心 APP下载
官方微信
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!