2022-06-30 20:52阅读: 216评论: 0推荐: 0

Spring Boot或Spring MVC前后端分离的项目跨域问题的解决方案

  • 简单请求
    • 非简单请求


      源和跨域

      • 源(origin)就是协议、域名和端口号。

        URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口全部相同,则表示他们同源。

      • 跨域

        协议、域名、端口有任何一个不同

      那么跨域问题就是CORS全称Cross-Origin Resource Sharing,意为跨域资源共享。当一个资源去访问另一个不同域名或者同域名不同端口的资源时,就会发出跨域请求。如果此时另一个资源不允许其进行跨域资源访问,那么访问的那个资源就会遇到跨域问题。

      URL是否跨域原因
      https://www.baidu.com/more/index.html不跨域三要素相同
      https://map.baidu.com/跨域域名不同
      http://www.baidu.com/index.html跨域协议不同
      https://www.baidu.com:81/index.html跨域端口号不同

      同源策略

      同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

      同源策略又分为以下两种:

      1. DOM同源策略:禁止对不同源页面DOM 进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
      2. XMLHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。

      CORS-跨域资源共享

      CORS是一种W3C标准,定义了当产生跨域问题的时候,客户端与服务端如何通信解决跨域问题。实际上就是前后端约定好定义一些自定义的http请求头,让客户端发起请求的时候能够让服务端识别出来该请求是过还是不过。

      浏览器将CORS请求分为简单请求非简单请求:

      简单请求

      简单请求必须满足以下两个条件:

      1. 请求方式必须是HEAD、GET、POST三种方法之一。
      2. Http请求头必须只能是:Accept、Accept-Lanuage、Content-Lanuage、Last-Event-ID、Content-Type,其中Content-Type只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain。

      非简单请求

      不满足简单请求条件的就是非简单请求。针对非简单请求,浏览器会发起预检请求。预检请求的意思是当浏览器检查到你的页面含有跨域请求的时候,会发送一个OPTIONS请求给对应的服务器,以检测服务器是否允许当前域名的跨域请求。如果服务端允许该域名请求,则返回204或200状态码,浏览器接收到允许请求时候再继续发送对应的GET/POST/PUT/DELETE请求。同时服务器端也会告知浏览器预检请求的缓存时长是多少,在这个时间范围内,浏览器不会再次发起预检请求。

      跨域解决方案

      • 使用 nginx代理
      • 使用 filter 添加头信息
      • 使用 @CrossOrigin 注解
      • 使用 proxy 代理
      • 使用cors方案
      • jsonp
      1. 使用nginx代理

        配置nginx.conf

        ... ...
        location =/api {
        	proxy_pass http://ip:port$request_uri;
        }
        ... ...
        

        缺点

        • 本地调试还会出现跨域问题(除非本地也部署nginx服务),但是服务器方面是一劳永逸。
      2. 使用 filter 添加头信息

        @Component
        public class OriginFilter implements Filter {
        
        @Override
        public void init(FilterConfig filterConfig) throws ServletException { }
        
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {undefined
        	HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        	HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
        	httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
        	httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
        	httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        	httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        	filterChain.doFilter(request, response);
        }
        
        @Override
        public void destroy() { }
        
        }
        
      3. 使用 @CrossOrigin 注解

        直接在Controller类上加 @CrossOrigin 注解即可

        缺点

        • 如果后端技术使用的不是 SpringBoot,后端代码还需要处理跨域问题
        • 浏览器直接访问 后端API,在某种程度上是不太安全的
      4. 使用proxy代理

        优点

        • 在浏览器中屏蔽了实际访问后端的 地址,相对安全
        • 后端代码不必要进行额外处理跨域

        缺点

        • 在浏览器中看不到后端访问的地址,开发阶段调试不太方便
      5. 使用cors方案

      @Configuration
      public class CorsConfig implements WebMvcConfigurer {
      	@Override
      	public void addCorsMappings(CorsRegistry registry) {
      			super.addCorsMappings(registry);
      			registry.addMapping("/**")
      			.allowedHeaders("*")
      			.allowedMethods("POST","GET")
      			.allowedOrigins("*");
      	
      	}
      }
      
      • addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。
      • allowedMethods:允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等。
      • allowedOrigins:允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:“http://www.baidu.com”,只有百度可以访问我们的跨域资源。
      • allowedHeaders:允许所有的请求header访问,可以自定义设置任意请求头信息,如:“X-YAUTH-TOKEN”

      注意:使用此方法配置之后再使用自定义拦截器时跨域相关配置就会失效。

      1. jsonp

        因为script标签是不受浏览器同源策略的影响,允许跨域请求资源(我们的每一个页面都引用了大量第三方js文件)。所以可以利用动态创建script标签,通过src属性发起跨域请求,这就是jsonp的原理。但是jsonp只支持GET请求,所以并不是一种好的方式。

      在这里插入图片描述
      JVM内存泄漏和内存溢出的原因
      JVM常用监控工具解释以及使用
      Redis 常见面试题(一)
      ClickHouse之MaterializeMySQL引擎(十)
      三种实现分布式锁的实现与区别
      线程池的理解以及使用

      号外!号外!

      最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。

      • 喜欢就收藏
      • 认同就点赞
      • 支持就关注
      • 疑问就评论

      一键四连,你的offer也四连

      ————————————————————————————————————————————————————————————————

      本文作者:Java技术债务
      原文链接:https://www.cuizb.top/myblog/article/1647266608
      版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

      posted @   Java技术债务  阅读(216)  评论(0编辑  收藏  举报
      点击右上角即可分享
      微信分享提示
      💬
      评论
      📌
      收藏
      💗
      关注
      👍
      推荐
      🚀
      回顶
      收起
      1. 1 404 not found REOL
      404 not found - REOL
      00:00 / 00:00
      An audio error has occurred.