zoukankan      html  css  js  c++  java
  • 跨域总结(整理)

    跨域

    一、跨域是什么?为什么会存在跨域?

      ①、广义的定义:一个域下的文档或脚本试图去请求另一个域下的资源,如:www.baidu.com去请求www.google.com下的资源;

          如类似:资源跳转(<a>标签链接、重定向、表单提交)、资源嵌入(<link>、<script>、<img>、<frame>等DOM标签)、脚本请求(JS发起的Ajax请求等)

        狭义的定义:由浏览器同源策略限制的一类请求场景,这也是我们通常说的跨域问题

      ②、因为浏览器的“同源策略

        ①、什么是同源策略?为什么要有同源策略?

          a、同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。

             所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

          b、浏览器施加的安全限制

    二、跨域的解决方式?

      1、 通过jsonp跨域
      2、 document.domain + iframe跨域
      3、 location.hash + iframe
      4、 window.name + iframe跨域
      5、 postMessage跨域
      6、 跨域资源共享(CORS)
      7、 nginx代理跨域
      8、 nodejs中间件代理跨域
      9、 WebSocket协议跨域

      此处就介绍一下:JSONP 跟 CORS 这两种方式

      ①、JSONP

        扩展:JSONP 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。

        JSON是描述信息的格式,JSONP是信息传递双方约定的方法。

        前端代码:

        a、原生方式:

          <script type="text/javascript" src="http://localhost:8080/api/test?callback=test"></script>
          <script type="text/javascript">
            function test(arg){
             //.....
            }
          </script>

         服务端返回如下(返回时即执行全局函数):test({"status": true, "user": "admin"})

        b、query ajax:
          $.ajax({       url: 'http://localhost.com:8080/login',       type: 'get',       dataType: 'jsonp', // 请求方式为jsonp       jsonpCallback: "test", // 自定义回调函数名       data: {}       });

         c、vue.js:

            this.$http.jsonp('http://www.domain2.com:8080/login',

                        { params: {}, jsonp: 'test' }

                      ).then((res) => { console.log(res); })

        后端代码:

        Java后端实现:        
            String callback = request.getParameter("callback");
           
            String data = new Gson().toJson(...);
            PrintWriter out = response.getWriter();
            out.write(callback + "(" + data + ")");
        Node.js后端实现:
          var querystring = require('querystring');       
    var http = require('http');       var server = http.createServer();       server.on('request', function(req, res) {       var params = qs.parse(req.url.split('?')[1]);         var fn = params.callback;         // jsonp返回设置         res.writeHead(200, { 'Content-Type': 'text/javascript' });         res.write(fn + '(' + JSON.stringify(params) + ')');         res.end();       });       server.listen('8080');       console.log('Server is running at port 8080...');
      ②、CORS
        普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置。
        带cookie请求:前后端都需要设置字段,另外需注意:所带cookie为跨域请求接口所在域的cookie,而非当前页。
        目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

        前端代码:
          a、原生ajax
              // 前端设置是否带cookie
              xhr.withCredentials = true;
            示例代码:
              var xhr = new XMLHttpRequest();  // IE8/9需用window.XDomainRequest兼容
              // 前端设置是否带cookie
              xhr.withCredentials = true;
              xhr.open('post', 'http://www.domain2.com:8080/login', true);
              xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
              xhr.send('user=admin');
              xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                  alert(xhr.responseText);
                }
              };
          b、JQuery ajax
            $.ajax({
              ...
              xhrFields: {
                withCredentials: true // 前端设置是否带cookie
              },
              crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
              ...
            });

          c、VUE
            框架在vue-resource封装的ajax组件中加入以下代码:
            Vue.http.options.credentials = true

        服务端设置:
          若后端设置成功,前端浏览器控制台则不会出现跨域报错信息,反之,说明没设成功。
          
    a、Java后台:
            
    response.setHeader("Access-Control-Allow-Origin", "http://localhost.com"); // 若有端口需写全(协议+域名+端口)
            response.setHeader("Access-Control-Allow-Credentials", "true");
          
    b、Nodejs后台示例:
           
     var http = require('http');
            var server = http.createServer();
            var qs = require('querystring');
            server.on('request', function(req, res) {
              var postData = '';
              // 数据块接收中
              req.addListener('data', function(chunk) {
                postData += chunk;
              });
              // 数据接收完毕
              req.addListener('end', function() {
                postData = qs.parse(postData);
                // 跨域后台设置
                res.writeHead(200, {
                  'Access-Control-Allow-Credentials': 'true',    // 后端允许发送Cookie
                  'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
                  'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'    // HttpOnly:脚本无法读取cookie
                });
                res.write(JSON.stringify(postData));
                res.end();
              });
            });
            server.listen('8080');
            console.log('Server is running at port 8080...');

        CORS高级应用:

      springmvc4.2版本增加了对cors的支持。

      目前我所做的项目基本都是springboot进行开发,所以我这里贴下在springboot中的使用。

    复制代码
    @Configuration
    public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    复制代码

      可以在addMapping中配置我们的路径。/**代表所有路径。

      当然也可以修改其它属性

    复制代码
    @Configuration
    public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
               registry.addMapping("/api/**")
               .allowedOrigins("http://192.168.1.97")
               .allowedMethods("GET", "POST")
               .allowCredentials(false).maxAge(3600);
        }
    复制代码

      以上两种,都是针对全局配置,如果你想做到更细致也可以使用@CrossOrigin这个注解在controller类中使用。

    @CrossOrigin(origins = "http://192.168.1.97:8080", maxAge = 3600)
    @RequestMapping("rest_index")
    @RestController
    public class IndexController{

      这样就可以指定该controller中所有方法都能处理来自http:19.168.1.97:8080中的请求。

  • 相关阅读:
    Mybatis学习(3)实现数据的增删改查
    Mybatis学习(2)以接口的方式编程
    Mybatis学习(1)开发环境搭建
    Apache Commons 工具类介绍及简单使用
    JAVA枚举使用详解
    Spring中的<context:annotation-config/>配置
    SpringMVC(12)完结篇 基于Hibernate+Spring+Spring MVC+Bootstrap的管理系统实现
    SpringMVC(11)表单标签
    面试题
    开发辅助网址
  • 原文地址:https://www.cnblogs.com/swugogo/p/9106017.html
Copyright © 2011-2022 走看看