zoukankan      html  css  js  c++  java
  • Springboot解决ajax跨域的三种方式

    1.同源策略 

    1.1 含义

      ajax出现请求跨域错误问题,主要原因就是因为浏览器的“同源策略”;1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。

    最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源"。所谓"同源"指的是"三个相同"。

    • 协议相同
    • 域名相同
    • 端口相同

      举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下:

    • http://www.example.com/dir2/other.html:同源
    • http://example.com/dir/other.html:不同源(域名不同)
    • http://v2.www.example.com/dir/other.html:不同源(域名不同)
    • http://www.example.com:81/dir/other.html:不同源(端口不同)

    1.2 目的

      同源策略的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

      设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

      由此可见,"同源策略"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

    1.3 限制范围

      随着互联网的发展,"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。

    (1) Cookie、LocalStorage 和 IndexDB 无法读取。

    (2) DOM 无法获得。

    (3) AJAX 请求不能发送。

    2.解决Ajax请求不能发送的问题

      本文只关注Ajax请求跨域问题,想了解更多可以参考:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html 

      同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

      除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

    • JSONP
    • WebSocket
    • CORS:(H5中的新特性:Cross-Origin Resource Sharing(跨域资源共享)。通过它,我们的开发者(主要指后端开发者)可以决定资源是否能被跨域访问。cors是一个w3c标准,它允许浏览器(目前ie8以下还不能被支持)像我们不同源的服务器发出xmlHttpRequest请求,我们可以继续使用ajax进行请求访问)

      本文中我们使用第三种方式来解决在Springboot项目中的跨域问题。前端发出Ajax请求访问Springboot(如在http://127.0.0.1:8086web项目中访问http://127.0.0.1:8866)服务时,Ajax跨域请求报错如下:

        $.ajax({
                url : "http://127.0.0.1:8866/index",
                type : "GET",
                dataType : "text",
                success : function(msg) {
                    $("#box").html(msg);
                    alert(msg);
                }
            });

      Access to XMLHttpRequest at 'http://127.0.0.1:8866/' from origin 'http://127.0.0.1:8086' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

      在http://127.0.0.1:8866这个服务中,我们有三种解决方式:

    2.1注解方式

      在需要跨域的Controller层的类或方法上加上注解:@CrossOrigin。这样就可以指定该controller中所有方法或某个方法处理所有或只来自http://127.0.0.1:8086中的请求。

    @Controller
    @CrossOrigin//@CrossOrigin(origins = "http://127.0.0.1:8086", maxAge = 3600)
    public class ApiController {
    
        //@CrossOrigin
        @GetMapping(value = "/index")
        public String index(HttpServletRequest request) {
            request.getSession().setMaxInactiveInterval(60*30);
    
            return "index";
        }
    }

    2.2 过滤器方式

      修改返回请求头信息:

    @Component
    public class CorsFilter implements Filter {
    
        private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                throws IOException, ServletException {
    
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers",
                    "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
    
            chain.doFilter(req, res);
        }
    
        @Override
        public void destroy() {
    
        }
    
    }

    2.3 继承WebMvcConfigurerAdapter,重写addCorsMappings方法:

    @Component
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
            .allowCredentials(true)
            .allowedOrigins("*")
            .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
            .maxAge(3600) 
            .allowedHeaders("*");
        }
    }

    OVER!

  • 相关阅读:
    C语言:运算结果保留两位小数
    FFmpeg: AVFrame中的data和extend_data的区别
    android studio: 配置版权信息(转)
    C++: C++11 成员函数作为pthread线程 (转)
    android studio: 取消行注释在第一列
    C 语言 int 读写是否需要加锁
    【转】浅析Linux中的零拷贝技术--简单形象
    【转】Linux 内核态与用户态--简明清晰的介绍
    delete如何找到多重继承对象的内存块起始地址
    【转】内存管理内幕mallco及free函数实现--简易内存分配器、内存池、GC技术
  • 原文地址:https://www.cnblogs.com/itfeng813/p/14151040.html
Copyright © 2011-2022 走看看