zoukankan      html  css  js  c++  java
  • No 'AccessControlAllowOrigin' header is present之跨域问题及解决方案

     如图,是在chome浏览器的Console中显示的信息,很明显,No 'Access-Control-Allow-Origin' header is present on the requested resource这句话表示出现了跨域请求问题,那么什么是跨域请求呢?

    一、何为“跨域”?

         跨域是浏览器对于javascript的同源策略的限制,一般我们使用ajax发送请求时会出现这种情况,举个栗子:A网站有一个请求路径为http:ip1:port1/aa,我们希望使用Ajax来获得B网站中的特定内容。而B网站的域名地址为http:ip2:prot2,只要ip和port有一个不一致,那么就出现了跨域访问问题。你可以理解为两个域名之间不能跨过域名来发送请求或者请求数据,否则就是不安全的。跨域访问违反了同源策略,同源策略规定,浏览器的ajax只能访问跟它的HTML页面同源(相同域名或IP)的资源。

    在讲跨域解决方案时,我们先来探讨一下http请求类型及浏览器发送跨域请求过程

      http请求一般常见的有GET,POST,请求header里面无自定义头,Content-Type为以下几种:text/plain  multipart/form-data application/x-www-form-urlencoded。此外还有非简单请求如put delete的ajax请求,发送json格式的ajax请求,带自定义头的ajax请求。

    如果是简单请求,浏览器会先发送请求,然后判断服务器返的返回头中是否支持跨域请求,否则抛出跨域异常

    如果是非简单请求,浏览器会先发出OPTIONS请求方法的检测命令,判断服务器是否支持跨域请求,如果支持则发送真正的请求,如果不支持则抛出跨域异常,因此一个非简单请求每次会发送两个请求
    跨域解决方案一般有以下几种:

    一、JSONP方式

    jsonp 全称是JSON with Padding,是为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。一个是描述信息的格式,一个是信息传递双方约定的方法。

    jsonp的产生:

    1.AJAX直接请求普通文件存在跨域无权限访问的问题,不管是静态页面也好.

    2.不过我们在调用js文件的时候又不受跨域影响,比如引入jquery框架的,或者是调用相片的时候

    3.凡是拥有scr这个属性的标签都可以跨域例如<script><img><iframe>

    4.如果想通过纯web端跨域访问数据只有一种可能,那就是把远程服务器上的数据装进js格式的文件里.

    5.而json又是一个轻量级的数据格式,还被js原生支持

    6.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback 参数给服务端,

    注意:使用JSONP方式实现跨域请求只能是get请求不能使用post请求

    不多说,直接上代码

    function testJSONPAPI() {
            $.ajax({
                type: "POST",
                async: true,
                dataType: "jsonp",
                jsonp:"callback",
                data: {
                    userName:"aaaaa"
                },
                url: "http://172.16.15.90:8080/user/getUserByJSONP",
                success: function (data) {
                    console.log(data);
                    
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    
                }
            });
        }
    

      后端代码:

    @ResponseBody
        @RequestMapping(value = "/getUserByJSONP", method = RequestMethod.GET)
        public String getMySeatSuccess(@RequestParam("callback") String callback, String userName) {
            Gson gson = new Gson();
            Map<String, String> map = new HashMap<>();
            map.put("userName", userName);
            return callback + "(" + gson.toJson(map) + ")";
        }


    需要注意的是:前端注意与后端沟通约定jsonp的值,通常默认都是用callback。后端根据jsonp参数名获取到参数后要与本来要返回的json数据按“callback(json)”的方式构造。

    二、服务端通过filter或者interceptor解决跨域

       既然No 'Access-Control-Allow-Origin' header is present,那我们就在服务端对所有跨域的请求url做一个拦截,在拦截器里动态添加上允许跨域请求就OK了,

    下面是最简单的一个允许跨域请求的拦截器

    public class RemoteInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse resp, Object handler) throws Exception {
    //        resp.addHeader("Access-Control-Allow-Origin","*");
            resp.setHeader("Access-Control-Allow-Origin","*");
            resp.setCharacterEncoding("UTF-8");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    
        }
    }

    三、通过springboot自带配置类中去配置

    @Configuration
    @EnableWebMvc
    @ComponentScan({"com.example.demo.controller", "com.example.demo.interceptors"})
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new RemoteInterceptor()).addPathPatterns("/**");
        }
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("*");
        }
    }
    少一些浮躁,多一份坚持,专注技术,砥砺前行。
  • 相关阅读:
    LeetCode Path Sum II
    LeetCode Longest Palindromic Substring
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Best Time to Buy and Sell Stock III
    LeetCode Binary Tree Maximum Path Sum
    LeetCode Find Peak Element
    LeetCode Maximum Product Subarray
    LeetCode Intersection of Two Linked Lists
    一天一个设计模式(1)——工厂模式
    PHP迭代器 Iterator
  • 原文地址:https://www.cnblogs.com/guoft-share/p/10594236.html
Copyright © 2011-2022 走看看