zoukankan      html  css  js  c++  java
  • aiax跨域问题

    aiax跨域问题

    问题说明

    假如我们有两个项目, 域名分别为 www.jt.com (web前端项目)manager.jt.com (后端项目)

    第一个项目中前端页面发送ajax请求到第二个项目中去处理, 显然是不成功的.

    同源策略

    同源策略针对的是ajax, 对a标签或script标签等无效

    浏览器中规定Ajax请求协议, 域名, 端口三者必须全部相同时,才能实现数据访问(同域请求),如果违反上述规则中的任意一个则该请求就是跨域访问.
    如果浏览器进行跨域访问,则浏览器不予解析返回值.

    也就是说, a标签跳转可以跳转到任何url页面, script也可以引入其他CDN网站的js文件, 但是ajax无法对其他应用的服务器发送请求

    JSONP前端实现跨域

    艺名:json"胖"
    JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通

    jQuery实现JSONP

    需求:jsonp的方式如果采用原生的调用方式,则配置繁琐 1.javascript 2.自定义回调函数 3.特殊格式封装.
    则jQuery负责封装JSONP.像常规ajax调用一样的方便.
    页面封装:

    1. JQuery代码如下

    $(function(){
        $.ajax({
            url:"http://manager.jt.com/web/testJSONP",
            type:"get",				//jsonp只能支持get请求   因为src只能进行get请求.
            dataType:"jsonp",       //dataType表示返回值类型 必须标识
            //jsonp: "callback",    //指定参数名称
            jsonpCallback: "hello",  //指定回调函数名称
            success:function (data){   //data经过jQuery封装返回就是json串
                alert(data.id);
                alert(data.name);
            }
        });	
    }
    

    jsonp请求会附带一个参数callback, 此参数记录的就是跨域请求回调的函数名, 类似于上面jsonp案例中的hello函数

    2. 对应的controller

    @RestController
    public class JSONPController {
    
        /**
         * 完成JSONP的调用
         * url:http://manager.jt.com/web/testJSONP?callback=jQuery111101021758391465013_1597656788213&_=1597656788214
         * 规定:返回值结果,必须经过特殊的格式封装.callback(json)
         */
        @RequestMapping("/web/testJSONP")
        public String  jsonp(String callback){
    
            return callback+"({'id':'100','name':'tomcat猫'})";
        }
    
    }
    

    如果每次都手动将对象转json再拼接, 就特别麻烦, 我们可以使用JsonpObject对象来作为controller来简化操作

    JsonpObject的构造方法: JsonpObject(String function, Object value)

    其中function是回调函数名, value是要传递的对象

    例如:

    @RequestMapping("/web/testJSONP")
    public JsonpObject jsonp(String callback) {
        Item item = new Item(); // 要传递的对象
        item.setXXX();
        // ... set一些数据
        
        return new JsonpObject(callback, item);
    }
    

    JSONP跨域思路

    既然script标签可以跨域, 是否可以间接使用script标签实现跨域呢?

    jsonp的跨域实现就是这个原理

    JSONP跨域原理

    1. 利用script中的src属性进行跨域!!!
    <script type="text/javascript" src="http://manager.jt.com/test.json"></script>
    

    补充说明:一般src属性负责资源的加载.如果 需要使用数据,则需要函数进行调用才行.

    1. 自定义回调函数, 例如: (data参数为接收的json数据)

    此代码需要放到对应的script标签上面, 不然请求会失败

    <script type="text/javascript">
        /*JS是解释执行的语言  */
        /*定义回调函数  */
        function hello(data){
            alert(data.name);
        }
    </script>
    
    1. 将返回值的结果 进行特殊的格式封装!!!
    hello({"id":"1","name":"tom"})
    

    案例就此完毕!

    完整代码如下:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>测试JSON跨域问题</title>	
            
            <script type="text/javascript">
                /*JS是解释执行的语言  */
                /*定义回调函数  */
                function hello(data){
                    alert(data.name);
                }
            </script>
            <!--  其他域名下的json请求, 该json一直保存到浏览器中等待调用,但是没有函数名称无法调用  -->
            <script type="text/javascript" src="http://manager.jt.com/test.json"></script>
            <!-- 引入JQuery -->
            <script type="text/javascript" src="http://manager.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
            </script>
        
        </head>
    
        <body>
            <h1>JS跨域问题</h1>
        </body>
    </html>
    

    这样就实现了请求的跨域, 也是jsonp实现跨域的原理和思路

    CORS服务端实现跨域

    CORS,全称Cross-Origin Resource Sharing [1] ,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制,通常由于同域安全策略(the same-origin security policy)浏览器会禁止这种跨域请求。
    知识回顾:

    • JSONP: 用户利用jsonp向服务器端动态获取数据的过程. 主体用户.
    • CORS: 服务器是否允许客户端访问的技术. 主体服务器.

    CORS原理说明

    用户可以向普通的ajax请求一样发起跨域请求. get/post/put/delete,由于当下的跨域的业务比较常见,所有的主流的浏览器默认支持跨域. CORS核心需要配置服务器端是否允许跨域

    例如常规ajax跨域请求

    <script type="text/javascript">
    	/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
    	$(function(){
    		alert("我执行了AJAX");
    		$.get("http://manager.jt.com/test.json",function(data){
    			alert(data.name);
    		})
    	})
    </script>
    

    页面报错信息. 表示服务器端暂时不允许跨域.

    springboot实现CORS跨域

    说明: 服务器端如果需要实现CORS跨域请求,则需要在服务器端标识允许跨域的网址即可.

    添加cors操作. MVC配置类如下

    @Configuration  //标识我是一个配置类
    public class CorsConfig implements WebMvcConfigurer {
    
        //扩展跨域请求的方法
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            //1.允许什么样的请求进行跨域
            // (/* 只允许一级目录请求)    (/** 表示多级目录请求.)
            registry.addMapping("/**")
            		//2.允许哪些服务进行跨域, 可以是单个或可变参数, 例如参数为 "http://www.jt.com" 
                    .allowedOrigins("*") // * 为通配符, 代表所有
                    //3.是否允许携带cookie信息
                    .allowCredentials(true)
                	//允许的请求方式, 默认GET/POST/HEAD
    				// .allowedMethods("GET","POST","PUT","DELETE","HEAD") 
                    //4.定义探针检测时间(秒) 在规定的时间内不再询问是否允许跨域, 默认为1800
                    .maxAge(1800);
        }
        
    }
    

    这样配置后, 其他服务器向此服务器发送ajax请求的时候(可以是get/post/put/delete等请求), 就可以实现跨域了

    CORS流程图

    即便是服务器允许跨域, 如果没有对应的响应头, 浏览器也不会正常接收数据 上述MVC配置会自动添加响应头信息

    CORS跨域响应信息.

    关于JSONP的全局异常处理

    有时候我们需要处理jsonp的异常, 但是普通json的异常返回值信息并没有函数的名字

    解决思路, jsonp的请求会有一个collback的参数, 我们可以检查是否有此参数, 如果有就是jsonp请求, 如果没有就是普通json请求

    @RestControllerAdvice   //定义异常处理的通知.  只拦截Controller层抛出的异常. 并且返回值JSON串
    public class SystemExceptionAOP {
    
        /**
         * 如果跨域访问发生了异常 ,则返回值结果必须经过特殊的格式封装才行.
         * 如果是跨域访问形式,全局异常处理 可以正确的返回结果.
         * 思路: 1.判断用户提交参数中是否有callback参数
         * callback(json)
         */
        @ExceptionHandler(RuntimeException.class)
        public Object fail(Exception e, HttpServletRequest request){
    
            //1.获取用户的请求参数
            String callback = request.getParameter("callback");
    
            //2.判断参数是否有值
            if(StringUtils.isEmpty(callback)){
                // 普通json请求的异常处理
            }else{
                // jsonp的请求异常处理
            }
        }
    }
    
  • 相关阅读:
    swift init继承问题
    CocoaPods 使用本地代码
    关于Xcode6 Segue 的疑问,没有解决!
    Cocos2d 学习资料推荐
    iOS8中 UILocalNotification 和 UIRemoteNotification 使用注意
    Cocos2d 初学基本知识
    iOS 和 Android 触摸事件传递
    iOS NSOperation的使用
    Android 相机对焦模式
    AES 推荐文章
  • 原文地址:https://www.cnblogs.com/zpKang/p/13520003.html
Copyright © 2011-2022 走看看